Я создаю экран для сканирования штрихкодов, и я должен поместить полупрозрачный экран позади некоторых UILabels
улучшить видимость против светлых фонов.
Вот то, на что экран похож теперь:
Я выбираю цвет фона на UILabel
получить полупрозрачные поля. Я также создал пользовательское UILabel
подкласс, чтобы позволить мне устанавливать некоторое дополнение между краем UILabel
и текст с помощью этого подхода.
Поскольку Вы видите на экране выше, UILabel
не изменяет размер правильно для принятия дополнения. "Дополнение" просто смещает текст, не изменяя ширину маркировки, заставляя текст усечь.
Обе из этих маркировок будут содержать текст произвольных длин, и мне действительно нужно UILabel
динамично изменить размер.
Что UILabel
метод я могу переопределить для увеличения ширины маркировки и фактора в дополнении?
Вот класс маркировки, который вычисляет размеры правильно. отправленный код находится в Swift 3, но можно также загрузить Swift 2 или Objective C версии.
Путем вычисления надлежащего textRect весь из sizeToFit
и автоматическая компоновка наполняет работы как ожидалось. Прием должен сначала вычесть вставки, затем вычислить исходные границы маркировки, и наконец добавить вставки снова.
class NRLabel : UILabel {
var textInsets = UIEdgeInsets.zero {
didSet { invalidateIntrinsicContentSize() }
}
override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
let insetRect = UIEdgeInsetsInsetRect(bounds, textInsets)
let textRect = super.textRect(forBounds: insetRect, limitedToNumberOfLines: numberOfLines)
let invertedInsets = UIEdgeInsets(top: -textInsets.top,
left: -textInsets.left,
bottom: -textInsets.bottom,
right: -textInsets.right)
return UIEdgeInsetsInsetRect(textRect, invertedInsets)
}
override func drawText(in rect: CGRect) {
super.drawText(in: UIEdgeInsetsInsetRect(rect, textInsets))
}
}
, Если Вы хотите установить текстовые вставки в раскадровках, можно использовать следующее расширение для включения Интерфейсной поддержки Разработчика:
@IBDesignable
extension NRLabel {
// currently UIEdgeInsets is no supported IBDesignable type,
// so we have to fan it out here:
@IBInspectable
var leftTextInset: CGFloat {
set { textInsets.left = newValue }
get { return textInsets.left }
}
// Same for the right, top and bottom edges.
}
Теперь можно удобно установить вставки в IB и затем просто нажать вЊ = для корректировки размера маркировки для установки.
Весь код находится в общественном достоянии. Поступать как угодно.
Вот версия Swift подкласса UILabel (то же как ответ @Nikolai), который создает дополнительное дополнение вокруг текста UILabel:
class EdgeInsetLabel : UILabel {
var edgeInsets:UIEdgeInsets = UIEdgeInsetsZero
override func textRectForBounds(bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
var rect = super.textRectForBounds(UIEdgeInsetsInsetRect(bounds, edgeInsets), limitedToNumberOfLines: numberOfLines)
rect.origin.x -= edgeInsets.left
rect.origin.y -= edgeInsets.top
rect.size.width += (edgeInsets.left + edgeInsets.right);
rect.size.height += (edgeInsets.top + edgeInsets.bottom);
return rect
}
override func drawTextInRect(rect: CGRect) {
super.drawTextInRect(UIEdgeInsetsInsetRect(rect, edgeInsets))
}
}
Вот версия C# (полезна для Xamarin) на основе кода Nikolai:
public class UIEdgeableLabel : UILabel
{
public UIEdgeableLabel() : base() { }
public UIEdgeableLabel(NSCoder coder) : base(coder) { }
public UIEdgeableLabel(CGRect frame) : base(frame) { }
protected UIEdgeableLabel(NSObjectFlag t) : base(t) { }
private UIEdgeInsets _edgeInset = UIEdgeInsets.Zero;
public UIEdgeInsets EdgeInsets
{
get { return _edgeInset; }
set
{
_edgeInset = value;
this.InvalidateIntrinsicContentSize();
}
}
public override CGRect TextRectForBounds(CGRect bounds, nint numberOfLines)
{
var rect = base.TextRectForBounds(EdgeInsets.InsetRect(bounds), numberOfLines);
return new CGRect(x: rect.X - EdgeInsets.Left,
y: rect.Y - EdgeInsets.Top,
width: rect.Width + EdgeInsets.Left + EdgeInsets.Right,
height: rect.Height + EdgeInsets.Top + EdgeInsets.Bottom);
}
public override void DrawText(CGRect rect)
{
base.DrawText(this.EdgeInsets.InsetRect(rect));
}
}
Быстро 5 версий ответа Nikolai Ruhe:
extension UIEdgeInsets {
func apply(_ rect: CGRect) -> CGRect {
return rect.inset(by: self)
}
}
class EdgeInsetLabel: UILabel {
var textInsets = UIEdgeInsets.zero {
didSet { invalidateIntrinsicContentSize() }
}
override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
let insetRect = bounds.inset(by: textInsets)
let textRect = super.textRect(forBounds: insetRect, limitedToNumberOfLines: numberOfLines)
let invertedInsets = UIEdgeInsets(top: -textInsets.top,
left: -textInsets.left,
bottom: -textInsets.bottom,
right: -textInsets.right)
return textRect.inset(by: invertedInsets)
}
override func drawText(in rect: CGRect) {
super.drawText(in: rect.inset(by: textInsets))
}}
В дополнениях к Nikolai Ruhe ответ, необходимо делать недействительным внутренний размер содержания для авторасположения для надлежащего перевычисления изменений размера. Вы заметили бы эту проблему при изменении edgeInsets по жизненному циклу приложения:
class NRLabel: UILabel {
var edgeInsets = UIEdgeInsetsZero {
didSet {
self.invalidateIntrinsicContentSize()
}
}
...
}
Вот пример того, что я использовал для простых 10 единиц, дополняющих слева и права на маркировку со скругленными углами. Просто установите текст метки для центрирования, это сам, и сделайте, это - класс IndentedLabel, и остальное заботится о себе. Для изменения дополнения просто увеличиваются или вниз rect.size.width + = (x)
class IndentedLabel: UILabel {
var edgeInsets:UIEdgeInsets = UIEdgeInsetsZero
override func textRectForBounds(bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
var rect = super.textRectForBounds(UIEdgeInsetsInsetRect(bounds, edgeInsets), limitedToNumberOfLines: numberOfLines)
rect.size.width += 20;
return rect
}
override func drawTextInRect(rect: CGRect) {
self.clipsToBounds = true
self.layer.cornerRadius = 3
super.drawTextInRect(UIEdgeInsetsInsetRect(rect, edgeInsets))
}
}
Вот быстрое, hacky способ сделать это, что можно понять более быстро. Это не столь устойчиво как Nikolai, но это сделало задание. Я сделал это, когда я пытался приспособить свой текст в моем UILabel в UITableViewCell:
let messageTextSize: CGSize = (messageText as NSString).sizeWithAttributes([
NSFontAttributeName: UIFont.systemFontOfSize(14.0)])
cell.widthConstraint.constant = messageTextSize.width + myInsetsOrWhatever
я еще экстенсивно не протестировал его, Вам, возможно, придется играть вокруг с точными значениями CGFloat, которые Вы добавляете. Я нашел, что правильный размер не является точно шириной плюс вставки; это немного больше, чем это. Это удостоверяется, что ширина UILabel всегда будет, по крайней мере, размером текста или больше.