Изменение размера UILabel для размещения вставок
Я создаю экран для сканирования штрих-кодов, и мне нужно поставить полупрозрачный экран позади некоторых UILabels для улучшения видимости на светлом фоне.
вот как теперь выглядит экран:

Я устанавливаю цвет фона на UILabel чтобы получить полупрозрачные ящики. Я также создал пользовательский UILabel подкласс, чтобы позволить мне установить некоторые отступы между краем UILabel и текст с помощью этот подходите.
как вы можете видеть на экране выше,UILabel не изменяет размер правильно, чтобы учесть заполнение. "Заполнение" просто сдвигает текст без изменения ширины метки, в результате чего текст усекается.
обе эти метки будут содержать текст произвольной длины, и мне действительно нужен UILabel для динамического изменения размера.
что UILabel метод можно переопределить, чтобы увеличить ширину метки и коэффициент в обивка?
6 ответов:
вот класс меток, который правильно вычисляет размеры. Элемент posted code находится в Swift 3, но вы также можете скачать Swift 2 или С версий.
как это работает?
путем вычисления правильного 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)) } }необязательно: поддержка построителя интерфейса
Если вы хотите настроить текстовые вставки в раскадровках, вы можете использовать следующее расширение для включения поддержки Interface Builder:
@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, а затем просто нажмите⌘=, чтобы настроить размер метки по размеру.
отказ от ответственности:
весь код находится в открытом доступе. Делайте, как вам угодно.
вот быстрая версия подкласса 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), основанная на коде Николая:
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)); } }
в дополнение к Николай Рухеответ, вам нужно аннулировать внутренний размер контента для автозапуска, чтобы правильно пересчитать изменения размера. Вы заметите эту проблему, если вы измените edgeInsets в течение жизненного цикла приложения:
class NRLabel: UILabel { var edgeInsets = UIEdgeInsetsZero { didSet { self.invalidateIntrinsicContentSize() } } ... }
вот пример того, что я использовал для простого заполнения 10 единиц слева и справа от метки с закругленными углами. Просто установите текст метки в центр, чтобы он был сам по себе, и сделайте его классом IndentedLabel, а остальное позаботится о себе. Чтобы изменить заполнение просто масштабировать вверх или вниз прямой.размер.ширина += (х)
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)) } }
вот быстрый, хаки способ сделать это, что вы можете понять быстрее. Он не такой крепкий, как у Николая, но он справляется с работой. Я сделал это, когда пытался вписать свой текст в мой UILabel в UITableViewCell:
- Установите ограничение ширины для UILabel
- подключите ограничение через IBOutlet к вашему коду, либо VC (пользовательский класс ячейки, если вы делаете расширяющуюся ячейку табличного представления)
- создать переменную для фактического размера текст, затем добавьте вставки + размер ширины к ограничению и обновите представление:
let messageTextSize: CGSize = (messageText as NSString).sizeWithAttributes([ NSFontAttributeName: UIFont.systemFontOfSize(14.0)]) cell.widthConstraint.constant = messageTextSize.width + myInsetsOrWhateverЯ еще не тщательно протестировал его, вам, возможно, придется поиграть с точными значениями CGFloat, которые вы добавляете. Я обнаружил, что правильный размер не совсем ширина плюс вставки; это немного больше, чем это. Это гарантирует, что ширина UILabel всегда будет по крайней мере размером текста или больше.
Comments