调整UILabel以适应插页

我正在构build一个扫描条形码的屏幕,我需要在一些UILabels后面放置一个半透明的屏幕,以提高对光线背景的可视性。

以下是屏幕现在的样子:

在这里输入图像描述

我在UILabel上设置背景颜色来获得半透明的盒子。 我还创build了一个自定义的UILabel子类,允许我使用这种方法在UILabel的边缘和文本之间设置一些填充。

正如你在上面的屏幕中看到的那样, UILabel不能正确resize来考虑填充。 “填充”只是移动文本而不改变标签的宽度,导致文本截断。

这两个标签将包含任意长度的文本,我真的需要UILabeldynamicresize。

我可以重写什么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)) } } 

可选: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子类的Swift版本(与@ Nikolai的答案相同),在UILabel的文本周围创build了一个额外的填充:

 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)) } } 

除了Nikolai Ruhe的回答,你需要使自动布局的内在内容大小无效,以正确地重新计算大小的变化。 如果在应用程序生命周期中更改edgeInsets,则会发现此问题:

 class NRLabel: UILabel { var edgeInsets = UIEdgeInsetsZero { didSet { self.invalidateIntrinsicContentSize() } } ... } 

这里是基于尼古拉的代码的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)); } } 

下面是一个例子,我用了一个简单的10单位填充在标签的左侧和右侧,圆angular。 只需将标签文本设置为居中,并将其设置为类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)) } } 

这是一个快速,哈希的方式来做到这一点,你可以更快地理解。 它不像尼古拉那样健壮,但它完成了工作。 当我试图在UITableViewCell中将我的文本放在我的UILabel中时,我这样做了:

  1. 为UILabel设置一个宽度约束
  2. 连接约束通过IBOutlet到你的代码,无论是VC(自定义单元格类,如果你正在做一个扩大表视图单元格)
  3. 为文本的实际大小创build一个variables,然后将insets +宽度大小添加到约束并更新视图:

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

我还没有广泛的testing它,你可能需要玩你添加的确切的CGFloat值。 我发现正确的大小不完全是宽度加插入; 比这大一点。 这可以确保UILabel的宽度至less为文本大小或更大。