我有一个UILabel,我想在顶部和底部添加空格。在限制最小高度的情况下,我将其修改为:

为了做到这一点,我使用了:

override func drawTextInRect(rect: CGRect) {
    var insets: UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 10.0, bottom: 0.0, right: 10.0)
    super.drawTextInRect(UIEdgeInsetsInsetRect(rect, insets))
}

但我必须找到不同的方法,因为如果我写了超过两行,问题是一样的:


当前回答

类似于其他答案,但使用func类来动态地设置填充:

class UILabelExtendedView: UILabel
{
    var topInset: CGFloat = 4.0
    var bottomInset: CGFloat = 4.0
    var leftInset: CGFloat = 8.0
    var rightInset: CGFloat = 8.0

    override func drawText(in rect: CGRect)
    {
        let insets: UIEdgeInsets = UIEdgeInsets(top: topInset, left: leftInset, bottom: bottomInset, right: rightInset)
        super.drawText(in: UIEdgeInsetsInsetRect(rect, insets))
    }

    override public var intrinsicContentSize: CGSize
    {
        var contentSize = super.intrinsicContentSize
        contentSize.height += topInset + bottomInset
        contentSize.width += leftInset + rightInset
        return contentSize
    }

    func setPadding(top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat){
        self.topInset = top
        self.bottomInset = bottom
        self.leftInset = left
        self.rightInset = right
        let insets: UIEdgeInsets = UIEdgeInsets(top: top, left: left, bottom: bottom, right: right)
        super.drawText(in: UIEdgeInsetsInsetRect(self.frame, insets))
    }
}

其他回答

我们最终找到了一个完整而正确的解决方案,它适用于所有情况,包括堆栈视图、动态单元格、动态行数、集合视图、动画填充、每个字符计数和所有其他情况。

填充一个UILabel,完整的解决方案。更新至2021年。

事实证明,有三件事是必须做的。

1. 必须调用textrect# forBounds与新的更小的大小

2. 必须重写drawText与新的更小的大小

3.如果是动态大小的单元格,必须调整intrinsicContentSize

在下面的典型示例中,文本单元位于表视图、堆栈视图或类似结构中,这给了它一个固定的宽度。在这个例子中,我们想要填充为60,20,20,24。

因此,我们使用“现有的”intrinsicContentSize并在高度上实际添加80。

重复一遍……

你必须从字面上“获得”引擎“到目前为止”计算的高度,并更改该值。

我觉得这个过程很混乱,但是,这就是它的工作原理。对我来说,苹果应该公开一个名为“初步高度计算”之类的调用。

其次,我们必须实际使用textrect# forBounds调用与我们的新小尺寸。

因此,在textrect# forBounds中,我们首先将大小减小,然后调用super。

警报!你必须在之后打电话给管理员,而不是在之前!

如果你仔细研究本页上的所有尝试和讨论,这就是问题所在。

注意一些解决方案“似乎通常有效”。这确实是确切的原因——令人困惑的是,你必须“事后打电话给超级”,而不是之前。

如果你“以错误的顺序”调用super,它通常会工作,但对于某些特定的文本长度会失败。

下面是一个“错误地先做超级”的直观例子:

注意,60,20,20,24边距是正确的,但大小计算实际上是错误的,因为它是用textrect# forBounds中的“super first”模式完成的。

修复:

只有现在textrect# forBounds引擎才知道如何正确地进行计算:

终于!

同样,在这个例子中,UILabel是在宽度固定的典型情况下使用的。因此,在intrinsicContentSize中,我们必须“添加”我们想要的整体额外高度。(你不需要以任何方式“添加”宽度,这将是没有意义的,因为它是固定的。)

然后在textrect# forBounds中,你通过自动布局得到了“建议到目前为止”的边界,你减去你的边距,然后才再次调用textrect# forBounds引擎,也就是说在super中,这将给你一个结果。

最后,在drawText中,你当然可以在同样小的方框中绘制。

唷!

let UIEI = UIEdgeInsets(top: 60, left: 20, bottom: 20, right: 24) // as desired

override var intrinsicContentSize:CGSize {
    numberOfLines = 0       // don't forget!
    var s = super.intrinsicContentSize
    s.height = s.height + UIEI.top + UIEI.bottom
    s.width = s.width + UIEI.left + UIEI.right
    return s
}

override func drawText(in rect:CGRect) {
    let r = rect.inset(by: UIEI)
    super.drawText(in: r)
}

override func textRect(forBounds bounds:CGRect,
                           limitedToNumberOfLines n:Int) -> CGRect {
    let b = bounds
    let tr = b.inset(by: UIEI)
    let ctr = super.textRect(forBounds: tr, limitedToNumberOfLines: 0)
    // that line of code MUST be LAST in this function, NOT first
    return ctr
}

再一次。请注意,关于这个问题和其他“几乎”正确的QA的答案会遇到上面第一张图中的问题——“super在错误的地方”。你必须在intrinsicContentSize中强制size更大,然后在textrect# forBounds中,你必须首先缩小第一个建议的边界,然后调用super。

总结:你必须在textrect# forBounds中“调用super last”

这就是秘诀。

请注意,您不需要也不应该需要额外调用invalidate、sizeThatFits、needsLayout或任何其他强制调用。正确的解决方案应该在正常的自动布局绘制周期中正常工作。

另一个没有子类化的选项是:

设置标签文本 sizeToFit () 然后稍微增加标签高度以模拟填充 标签。text = "someText" 标签。textAlignment = .center label.sizeToFit () label.frame = CGRect(x: label.frame.x, y: label.frame.y,width: label.frame.width + 20,height: label.frame.height + 8)

子类UILabel。(File-New-File- CocoaTouchClass-make UILabel的子类)。

//  sampleLabel.swift

import UIKit

class sampleLabel: UILabel {

 let topInset = CGFloat(5.0), bottomInset = CGFloat(5.0), leftInset = CGFloat(8.0), rightInset = CGFloat(8.0)

 override func drawTextInRect(rect: CGRect) {

  let insets: UIEdgeInsets = UIEdgeInsets(top: topInset, left: leftInset, bottom: bottomInset, right: rightInset)
  super.drawTextInRect(UIEdgeInsetsInsetRect(rect, insets))

 }
 override func intrinsicContentSize() -> CGSize {
  var intrinsicSuperViewContentSize = super.intrinsicContentSize()
  intrinsicSuperViewContentSize.height += topInset + bottomInset
  intrinsicSuperViewContentSize.width += leftInset + rightInset
  return intrinsicSuperViewContentSize
 }
}

ViewController:

override func viewDidLoad() {
  super.viewDidLoad()

  let labelName = sampleLabel(frame: CGRectMake(0, 100, 300, 25))
  labelName.text = "Sample Label"
  labelName.backgroundColor =  UIColor.grayColor()

  labelName.textColor = UIColor.redColor()
  labelName.shadowColor = UIColor.blackColor()
  labelName.font = UIFont(name: "HelveticaNeue", size: CGFloat(22))
  self.view.addSubview(labelName)
 }

或者将Storyboard上的自定义UILabel类关联为Label的类。

我的解决方案与人们回答的类似,但添加了sizeThatFits来帮助UIKit找出正确的大小。

class InsetLabel : UILabel {
    @objc var textInsets: UIEdgeInsets = .zero

    override func drawText(in rect: CGRect) {
        super.drawText(in: rect.inset(by: textInsets))
    }

    override func sizeThatFits(_ size: CGSize) -> CGSize {
        var s = super.sizeThatFits(CGSize(width: size.width - (textInsets.left + textInsets.right), height: size.height - (textInsets.top + textInsets.bottom)))
        s.height += textInsets.top + textInsets.bottom
        return s
    }
}

简单的方法

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.view.addSubview(makeLabel("my title",x: 0, y: 100, w: 320, h: 30))
    }

    func makeLabel(title:String, x:CGFloat, y:CGFloat, w:CGFloat, h:CGFloat)->UILabel{
        var myLabel : UILabel = UILabel(frame: CGRectMake(x,y,w,h))
        myLabel.textAlignment = NSTextAlignment.Right

        // inser last char to right
        var titlePlus1char = "\(title)1"
        myLabel.text = titlePlus1char
        var titleSize:Int = count(titlePlus1char)-1

        myLabel.textColor = UIColor(red:1.0, green:1.0,blue:1.0,alpha:1.0)
        myLabel.backgroundColor = UIColor(red: 214/255, green: 167/255, blue: 0/255,alpha:1.0)


        // create myMutable String
        var myMutableString = NSMutableAttributedString()

        // create myMutable font
        myMutableString = NSMutableAttributedString(string: titlePlus1char, attributes: [NSFontAttributeName:UIFont(name: "HelveticaNeue", size: 20)!])

        // set margin size
        myMutableString.addAttribute(NSFontAttributeName, value: UIFont(name: "HelveticaNeue", size: 10)!, range: NSRange(location: titleSize,length: 1))

        // set last char to alpha 0
        myMutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor(red:1.0, green:1.0,blue:1.0,alpha:0), range: NSRange(location: titleSize,length: 1))

        myLabel.attributedText = myMutableString

        return myLabel
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}