Изменение размера UILabel для размещения вставок



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



вот как теперь выглядит экран:



enter image description here



Я устанавливаю цвет фона на UILabel чтобы получить полупрозрачные ящики. Я также создал пользовательский UILabel подкласс, чтобы позволить мне установить некоторые отступы между краем UILabel и текст с помощью этот подходите.



как вы можете видеть на экране выше,UILabel не изменяет размер правильно, чтобы учесть заполнение. "Заполнение" просто сдвигает текст без изменения ширины метки, в результате чего текст усекается.



обе эти метки будут содержать текст произвольной длины, и мне действительно нужен UILabel для динамического изменения размера.



что UILabel метод можно переопределить, чтобы увеличить ширину метки и коэффициент в обивка?

467   6  

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:

  1. Установите ограничение ширины для UILabel
  2. подключите ограничение через IBOutlet к вашему коду, либо VC (пользовательский класс ячейки, если вы делаете расширяющуюся ячейку табличного представления)
  3. создать переменную для фактического размера текст, затем добавьте вставки + размер ширины к ограничению и обновите представление:

let messageTextSize: CGSize = (messageText as NSString).sizeWithAttributes([ NSFontAttributeName: UIFont.systemFontOfSize(14.0)]) cell.widthConstraint.constant = messageTextSize.width + myInsetsOrWhatever

Я еще не тщательно протестировал его, вам, возможно, придется поиграть с точными значениями CGFloat, которые вы добавляете. Я обнаружил, что правильный размер не совсем ширина плюс вставки; это немного больше, чем это. Это гарантирует, что ширина UILabel всегда будет по крайней мере размером текста или больше.

Comments

    Ничего не найдено.