添加空间/填充到UILabel

时间:2014-12-13 14:14:47

标签: ios uilabel padding

我有UILabel我希望在顶部和底部添加空格。 在最小高度的约束下,我将其修改为:

enter image description here

编辑: 为此,我使用了:

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

    } 

但是我找到了一种不同的方法,因为如果我写两行以上,问题是一样的:

enter image description here

37 个答案:

答案 0 :(得分:149)

我已尝试使用 Swift 4.2 ,希望它对您有用!

@IBDesignable class PaddingLabel: UILabel {

    @IBInspectable var topInset: CGFloat = 5.0
    @IBInspectable var bottomInset: CGFloat = 5.0
    @IBInspectable var leftInset: CGFloat = 7.0
    @IBInspectable var rightInset: CGFloat = 7.0

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

    override var intrinsicContentSize: CGSize {
        let size = super.intrinsicContentSize
        return CGSize(width: size.width + leftInset + rightInset,
                      height: size.height + topInset + bottomInset)
    }    
}

或者你可以在这里使用CocoaPods https://github.com/levantAJ/PaddingLabel

pod 'PaddingLabel', '1.1'

答案 1 :(得分:94)

如果你想坚持使用UILabel而不进行子类化,Mundi已经给你一个明确的解决方案。

如果您愿意避免使用UIView包装UILabel,您可以使用UITextView来启用UIEdgeInsets(填充)或子类UILabel以支持UIEdgeInsets。

使用 UITextView ,您只需要提供插图(OBJ-C):

textView.textContainerInset = UIEdgeInsetsMake(10, 0, 10, 0);

替代方案,如果您继承 UILabel ,此方法的一个示例将覆盖 drawTextInRect 方法
(OBJ-C)

- (void)drawTextInRect:(CGRect)uiLabelRect {
    UIEdgeInsets myLabelInsets = {10, 0, 10, 0};
    [super drawTextInRect:UIEdgeInsetsInsetRect(uiLabelRect, myLabelInsets)];
}

您还可以为新的子类UILabel提供TOP,LEFT,BOTTOM和RIGHT的insets变量。

示例代码可以是:

在.h(OBJ-C)

float topInset, leftInset,bottomInset, rightInset;

在.m(OBJ-C)

- (void)drawTextInRect:(CGRect)uiLabelRect {
    [super drawTextInRect:UIEdgeInsetsInsetRect(uiLabelRect, UIEdgeInsetsMake(topInset,leftInset,bottomInset,rightInset))];
}

编辑#1:

从我所看到的情况看,你似乎必须在继承它时重写UILabel的intrinsicContentSize。

所以你应该覆盖 intrinsicContentSize ,如:

- (CGSize) intrinsicContentSize {
    CGSize intrinsicSuperViewContentSize = [super intrinsicContentSize] ;
    intrinsicSuperViewContentSize.height += topInset + bottomInset ;
    intrinsicSuperViewContentSize.width += leftInset + rightInset ;
    return intrinsicSuperViewContentSize ;
}

并添加以下方法来编辑插图,而不是单独编辑它们:

- (void) setContentEdgeInsets:(UIEdgeInsets)edgeInsets {
    topInset = edgeInsets.top;
    leftInset = edgeInsets.left;
    rightInset = edgeInsets.right; 
    bottomInset = edgeInsets.bottom;
    [self invalidateIntrinsicContentSize] ;
}

它将更新UILabel的大小以匹配边缘插入,并涵盖您引用的多线必需性。

编辑#2

搜索了一下之后,我发现了Gist和IPInsetLabel。如果这些解决方案都不起作用,您可以尝试一下。

编辑#3

关于这件事有类似的问题(重复) 有关可用解决方案的完整列表,请参阅以下答案: UILabel text margin

答案 2 :(得分:75)

Swift 3

import UIKit

class PaddingLabel: UILabel {

   @IBInspectable var topInset: CGFloat = 5.0
   @IBInspectable var bottomInset: CGFloat = 5.0
   @IBInspectable var leftInset: CGFloat = 5.0
   @IBInspectable var rightInset: CGFloat = 5.0

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

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

答案 3 :(得分:65)

你可以从IB正确地做到这一点:

  1. 将文字更改为归属
  2. attributed text

    1. 使用" ..."进入下拉列表
    2. enter image description here

      1. 你会看到行,段落和文字的一些填充属性改变缩进第一行或你想要的任何东西
      2. enter image description here

        1. 检查结果
        2. enter image description here

答案 4 :(得分:42)

SWIFT 4

易于使用的解决方案,适用于项目中的所有UILabel儿童。

示例:

let label = UILabel()
    label.<Do something>
    label.padding = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 0)

UILabel扩展程序

import UIKit

extension UILabel {
    private struct AssociatedKeys {
        static var padding = UIEdgeInsets()
    }

    public var padding: UIEdgeInsets? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.padding) as? UIEdgeInsets
        }
        set {
            if let newValue = newValue {
                objc_setAssociatedObject(self, &AssociatedKeys.padding, newValue as UIEdgeInsets?, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    }

    override open func draw(_ rect: CGRect) {
        if let insets = padding {
            self.drawText(in: rect.inset(by: insets))
        } else {
            self.drawText(in: rect)
        }
    }

    override open var intrinsicContentSize: CGSize {
        guard let text = self.text else { return super.intrinsicContentSize }

        var contentSize = super.intrinsicContentSize
        var textWidth: CGFloat = frame.size.width
        var insetsHeight: CGFloat = 0.0
        var insetsWidth: CGFloat = 0.0

        if let insets = padding {
            insetsWidth += insets.left + insets.right
            insetsHeight += insets.top + insets.bottom
            textWidth -= insetsWidth
        }

        let newSize = text.boundingRect(with: CGSize(width: textWidth, height: CGFloat.greatestFiniteMagnitude),
                                        options: NSStringDrawingOptions.usesLineFragmentOrigin,
                                        attributes: [NSAttributedString.Key.font: self.font], context: nil)

        contentSize.height = ceil(newSize.size.height) + insetsHeight
        contentSize.width = ceil(newSize.size.width) + insetsWidth

        return contentSize
    }
}

答案 5 :(得分:37)

只需使用UIView作为超级视图,并使用自动布局为标签定义固定边距。

答案 6 :(得分:27)

只需使用已经内置的UIButton。关闭所有额外的按钮功能,你就有了一个可以设置边缘文字的标签。

let button = UIButton()
button.contentEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
button.setTitle("title", for: .normal)
button.tintColor = .white // this will be the textColor
button.isUserInteractionEnabled = false

答案 7 :(得分:13)

没有故事板:

class PaddingLabel: UILabel {

    var topInset: CGFloat
    var bottomInset: CGFloat
    var leftInset: CGFloat
    var rightInset: CGFloat

    required init(withInsets top: CGFloat, _ bottom: CGFloat,_ left: CGFloat,_ right: CGFloat) {
        self.topInset = top
        self.bottomInset = bottom
        self.leftInset = left
        self.rightInset = right
        super.init(frame: CGRect.zero)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

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

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

用法:

let label = PaddingLabel(8, 8, 16, 16)
label.font = .boldSystemFont(ofSize: 16)
label.text = "Hello World"
label.backgroundColor = .black
label.textColor = .white
label.textAlignment = .center
label.layer.cornerRadius = 8
label.clipsToBounds = true
label.sizeToFit()

view.addSubview(label)

结果:

答案 8 :(得分:8)

Swift 3代码及实施示例

class UIMarginLabel: UILabel {

    var topInset:       CGFloat = 0
    var rightInset:     CGFloat = 0
    var bottomInset:    CGFloat = 0
    var leftInset:      CGFloat = 0

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

class LabelVC: UIViewController {

    //Outlets
    @IBOutlet weak var labelWithMargin: UIMarginLabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        //Label settings.
        labelWithMargin.leftInset = 10
        view.layoutIfNeeded()
    }
}

不要忘记在storyboard标签对象中添加类名UIMarginLabel。 快乐的编码!

答案 9 :(得分:6)

根据 Swift 4.2 (Xcode 10 beta 6),已弃用“ UIEdgeInsetsInsetRect”。 我还宣布该类为公开课程,以使其更有用。

public class UIPaddedLabel: UILabel {

    @IBInspectable var topInset: CGFloat = 5.0
    @IBInspectable var bottomInset: CGFloat = 5.0
    @IBInspectable var leftInset: CGFloat = 7.0
    @IBInspectable var rightInset: CGFloat = 7.0

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

    public override var intrinsicContentSize: CGSize {
        let size = super.intrinsicContentSize
        return CGSize(width: size.width + leftInset + rightInset,
                      height: size.height + topInset + bottomInset)
    }

    public override func sizeToFit() {
        super.sizeThatFits(intrinsicContentSize)
    }
}

答案 10 :(得分:6)

Swift 3,iOS10解决方案:

def add_location_exe(request):
    if request.method == 'POST':
        ln = UserLocForm(request.POST or None)
        if ln.is_valid():
            name = ln.cleaned_data.get("name")
            ## is name in userloc list ##

答案 11 :(得分:5)

我在接受的答案中编辑了一点。 leftInsetrightInset增加时会出现问题,文本的一部分会消失,b / c标签的宽度会缩小,但高度不会增加,如图所示:

padding label with wrong intrinsic content size

要解决此问题,您需要重新计算文字高度,如下所示:

@IBDesignable class PaddingLabel: UILabel {

  @IBInspectable var topInset: CGFloat = 20.0
  @IBInspectable var bottomInset: CGFloat = 20.0
  @IBInspectable var leftInset: CGFloat = 20.0
  @IBInspectable var rightInset: CGFloat = 20.0

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

  override func intrinsicContentSize() -> CGSize {
    var intrinsicSuperViewContentSize = super.intrinsicContentSize()

    let textWidth = frame.size.width - (self.leftInset + self.rightInset)
    let newSize = self.text!.boundingRectWithSize(CGSizeMake(textWidth, CGFloat.max), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: self.font], context: nil)
    intrinsicSuperViewContentSize.height = ceil(newSize.size.height) + self.topInset + self.bottomInset

    return intrinsicSuperViewContentSize
  }
}

和结果:

padding label with right intrinsic content size

我希望能帮助处理与我相同情况的人。

答案 12 :(得分:5)

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

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

或者将故事板上的自定义UILabel类关联为Label的类。

答案 13 :(得分:3)

在Swift 3中

最简单的方法

class UILabelPadded: UILabel {
     override func drawText(in rect: CGRect) {
     let insets = UIEdgeInsets.init(top: 0, left: 5, bottom: 0, right: 5)
     super.drawText(in: UIEdgeInsetsInsetRect(rect, insets))
    }

}

答案 14 :(得分:3)

只需使用autolayout:

let paddedWidth = myLabel.intrinsicContentSize.width + 2 * padding
myLabel.widthAnchor.constraint(equalToConstant: paddedWidth).isActive = true

完成。

答案 15 :(得分:3)

快速4 +

class EdgeInsetLabel: UILabel {
    var textInsets = UIEdgeInsets.zero {
        didSet { invalidateIntrinsicContentSize() }
    }

    override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
        let textRect = super.textRect(forBounds: bounds, 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))
    } 
}

用法:

let label = EdgeInsetLabel()
label.textInsets = UIEdgeInsets(top: 2, left: 6, bottom: 2, right: 6)

答案 16 :(得分:2)

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

  1. 设置标签text
  2. sizeToFit()
  3. 然后稍微增加标签高度以模拟填充

    label.text = "someText"
    label.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)
    

答案 17 :(得分:2)

详细阐述了Mundi的答案。

即。在UIView中嵌入标签并通过自动布局强制执行填充。例如:

looks like a padded UILabel

<强>概述:

1)创建UIView(&#34;面板&#34;),并设置其外观。

2)创建UILabel并将其添加到面板。

3)添加约束以强制填充。

4)将面板添加到视图层次结构中,然后定位面板。

<强>详细信息:

1)创建面板视图。

let panel = UIView()
panel.backgroundColor = .green
panel.layer.cornerRadius = 12

2)创建标签,将其作为子视图添加到面板中。

let label = UILabel()
panel.addSubview(label)

3)在标签边缘和面板之间添加约束。这会强制面板与标签保持一定距离。即&#34;填充&#34;

编辑:手工完成这一切是非常乏味,冗长和容易出错的。我建议你从github中选择一个自动布局包装器或自己写一个

label.panel.translatesAutoresizingMaskIntoConstraints = false
label.topAnchor.constraint(equalTo: panel.topAnchor,
    constant: vPadding).isActive = true
label.bottomAnchor.constraint(equalTo: panel.bottomAnchor,
    constant: -vPadding).isActive = true
label.leadingAnchor.constraint(equalTo: panel.leadingAnchor,
    constant: hPadding).isActive = true
label.trailingAnchor.constraint(equalTo: panel.trailingAnchor,
    constant: -hPadding).isActive = true

label.textAlignment = .center

4)将面板添加到视图层次结构中,然后添加定位约束。例如拥抱tableViewCell的右侧,如示例图像。

注意:您只需要添加位置约束,而不是尺寸约束:自动布局将根据标签的intrinsicContentSize和之前添加的约束来解决布局。

hostView.addSubview(panel)
panel.translatesAutoresizingMaskIntoConstraints = false
panel.trailingAnchor.constraint(equalTo: hostView.trailingAnchor,
    constant: -16).isActive = true
panel.centerYAnchor.constraint(equalTo: hostView.centerYAnchor).isActive = true

答案 18 :(得分:2)

轻松填充(Swift 3.0,Alvin George回答):

  class NewLabel: UILabel {

        override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
                return self.bounds.insetBy(dx: CGFloat(15.0), dy: CGFloat(15.0))
        }

        override func draw(_ rect: CGRect) {
                super.drawText(in: self.bounds.insetBy(dx: CGFloat(5.0), dy: CGFloat(5.0)))
        }

  }

答案 19 :(得分:2)

就像其他答案一样,但修复了一个错误。 通过自动布局控制@IBDesignable class InsetLabel: UILabel { @IBInspectable var topInset: CGFloat = 4.0 @IBInspectable var leftInset: CGFloat = 4.0 @IBInspectable var bottomInset: CGFloat = 4.0 @IBInspectable var rightInset: CGFloat = 4.0 var insets: UIEdgeInsets { get { return UIEdgeInsets.init(top: topInset, left: leftInset, bottom: bottomInset, right: rightInset) } set { topInset = newValue.top leftInset = newValue.left bottomInset = newValue.bottom rightInset = newValue.right } } override func sizeThatFits(_ size: CGSize) -> CGSize { var adjSize = super.sizeThatFits(size) adjSize.width += leftInset + rightInset adjSize.height += topInset + bottomInset return adjSize } override var intrinsicContentSize: CGSize { let systemContentSize = super.intrinsicContentSize let adjustSize = CGSize(width: systemContentSize.width + leftInset + rightInset, height: systemContentSize.height + topInset + bottomInset) if adjustSize.width > preferredMaxLayoutWidth && preferredMaxLayoutWidth != 0 { let constraintSize = CGSize(width: bounds.width - (leftInset + rightInset), height: .greatestFiniteMagnitude) let newSize = super.sizeThatFits(constraintSize) return CGSize(width: systemContentSize.width, height: ceil(newSize.height) + topInset + bottomInset) } else { return adjustSize } } override func drawText(in rect: CGRect) { super.drawText(in: rect.inset(by: insets)) } } 时,有时会裁切文本。

outputPaths: {
  app: {
    css: {
      app: '/assets/custom-name.css'
    }
  }
},

答案 20 :(得分:1)

与其他答案类似,但使用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))
    }
}

答案 21 :(得分:1)

执行此操作的唯一正确方法:

事实证明,必须完成三件事

1。必须使用新的较小尺寸调用textRect#forBounds

2。必须以较小的新尺寸覆盖drawText

3。如果是动态尺寸的单元格,则必须调整internalContentSize

在此典型示例中,文本单元处于表格视图,堆栈视图或类似的结构中,从而赋予其固定宽度。在示例中,我们希望填充为60、20、20、24。

因此,我们采用“现有的” internalContentSize ,实际上将高度增加了80

要重复...

  

您必须从字面上“获取”由引擎“到目前为止”计算出的高度,然后更改该值。

我发现这令人困惑,但这就是它的工作原理。对我来说,Apple应该公开一个名为“初步高度计算”的呼叫。

第二,我们必须实际使用具有较小尺寸的textRect#forBounds呼叫

因此,在textRect#forBounds中,我们首先 使尺寸变小,然后 然后 调用超级。

此页面上只有几个答案接近有效:以前我们使用@ LE24给出的模式。但这就是确切的问题-您必须先在textRect#forBounds中调整大小,然后再调用super。

如果您以错误的方式进行操作,通常会起作用,但不适用于某些特定的文本长度。这是“不正确地做超级第一”的示例:

enter image description here

请注意60,20,20,24页边距是正确的,但是大小计算实际上是错误的,因为它是使用textRect#forBounds中的“超级第一”模式完成的。

已修复:

现在只有textRect#forBounds引擎知道如何正确执行计算:

enter image description here

最后!

同样,在此示例中,UILabel在宽度固定的典型情况下使用。因此,在internalContentSize中,我们必须“添加”所需的总体额外高度。 (您不需要以任何方式在宽度上“添加”,因为它是固定的,所以毫无意义。)

然后在textRect#forBounds中,通过自动布局获得“建议的边界”,您 减去 边距, 然后仅此 再次调用textRect#forBounds引擎,换句话说就是super,它将为您提供结果。

最后,在drawText中,您当然会在同一较小的框中绘制。

Ph!

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

override var intrinsicContentSize:CGSize {
    numberOfLines = 0       // don't forget!
    var s = super.intrinsicContentSize
    s.height = s.height + 60.0 + 20.0
    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)
    return ctr
}

再次。请注意,此和其他QA上“几乎”正确的答案在上面的第一张图片中遇到了问题- “ super的位置不正确” 。您必须在internalContentSize中强制增大大小,然后在 必须首先 的textRect#forBounds中将其缩小,首先缩小建议范围 ,然后 < / strong>叫超级。

摘要:您必须在textRect#forBounds中“调用超级 last

那是秘密。

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

答案 22 :(得分:1)

Objective-C

基于此处的Tai Le答案,该答案实现了IB Designable内部的功能,这是Objective-C版本。

将此内容放入YourLabel.h

@interface YourLabel : UILabel

@property IBInspectable CGFloat topInset;
@property IBInspectable CGFloat bottomInset;
@property IBInspectable CGFloat leftInset;
@property IBInspectable CGFloat rightInset;

@end

这将放在YourLabel.m

IB_DESIGNABLE

@implementation YourLabel

#pragma mark - Super

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        self.topInset = 0;
        self.bottomInset = 0;
        self.leftInset = 0;
        self.rightInset = 0;
    }
    return self;
}

- (void)drawTextInRect:(CGRect)rect {
    UIEdgeInsets insets = UIEdgeInsetsMake(self.topInset, self.leftInset, self.bottomInset, self.rightInset);
    [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
}

- (CGSize)intrinsicContentSize {

    CGSize size = [super intrinsicContentSize];
    return CGSizeMake(size.width + self.leftInset + self.rightInset,
                      size.height + self.topInset + self.bottomInset);
}

@end

然后,您可以在XIB或情节提要中指定类后直接在Interface Builder中修改YourLabel插图,这些插图的默认值为零。

答案 23 :(得分:1)

严格用于单行标签:(2021 语法)

对于任何只需要在严格单行标签(例如节标题或其他列表项)上填充的人来说,

语法发生了很大变化。这是要复制和粘贴的确切类:

// add 100 above, 50 padding below a SINGLE-LINE label
import UIKit
class SingleLineLabelWithSpacing: UILabel {
    // STRICTLY for SINGLE LINE labels
    // only works with SINGLE LINE labels

    override func drawText(in rect: CGRect) {
        let insets: UIEdgeInsets = UIEdgeInsets(
               top: 100, left: 0, bottom: 50, right: 0)
        super.drawText(in: rect.inset(by: insets))
    }

    override var intrinsicContentSize: CGSize {
        var ic = super.intrinsicContentSize
        ic.height = ic.height + 150
        return ic
    }
}

enter image description here

注意 100/50 以上/以下的填充。

当您有任何类型的滚动列表、提要或其他列表时,这是通常的做法。

通过这种方式,您无需考虑标题上方/下方的间距、用户名等 - 您只需将其放在堆栈视图中或其他任何情况下即可。

当然,当设计师想要调整时,您也可以在任何地方一次性更改这两个值。

提醒:如果你想真正地填充一个 UILabel 以便它完美地工作而不管文本的行数、动态调整单元格等等等等,这是非常复杂的。正确答案在“适用于所有情况的完整正确解决方案”下方。

答案 24 :(得分:1)

如果您不想或不需要在Storyboard中使用@IBInspectable / @IBDesignable UILabel(我认为它们渲染得太慢了),那么使用UIEdgeInsets而不是4种不同的CGFloats会更干净。

Swift 4.2的代码示例:

class UIPaddedLabel: UILabel {
    var padding = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)

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

    public override var intrinsicContentSize: CGSize {
        let size = super.intrinsicContentSize
        return CGSize(width: size.width + padding.left + padding.right,
                      height: size.height + padding.top + padding.bottom)
    }
}

答案 25 :(得分:1)

如果要在textRect周围添加2px填充,只需执行以下操作:

let insets = UIEdgeInsets(top: -2, left: -2, bottom: -2, right: -2)
label.frame = UIEdgeInsetsInsetRect(textRect, insets)

答案 26 :(得分:1)

简单方法

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

}

答案 27 :(得分:0)

如果您想使用 UILabel

class UILabel : UIKit.UILabel {
    var insets = UIEdgeInsets.zero {
        didSet { invalidateIntrinsicContentSize() }
    }

    override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
        let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
        let invertedInsets = UIEdgeInsets(top: -insets.top,
                                          left: -insets.left,
                                          bottom: -insets.bottom,
                                          right: -insets.right)
        return textRect.inset(by: invertedInsets)
    }

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

答案 28 :(得分:0)

一个实用的解决方案是添加与主标签具有相同高度和颜色的空白标签。将主标签的前/后空格设置为零,对齐垂直中心,并使宽度成为所需的边距。

答案 29 :(得分:0)

我在任何地方都没有看到这个答案。我的技术是在标签上设置宽度约束,并在设置标签文本时调整宽度。

self.myLabel.text = myString;

UIFont * const font = [UIFont systemFontOfSize:17 weight:UIFontWeightRegular]; // Change to your own label font.

CGSize const size = CGSizeMake(INFINITY, 18); // 18 is height of label.

CGFloat const textWidth = [myString boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: font} context:nil].size.width;

self.myLabelWidthConstraint.constant = textWidth + 20; // 10 padding on each side. Also, set text alignment to centre.

答案 30 :(得分:0)

带有UILabel扩展的Swift 5示例

使用下面的代码来设置边距就像label.setMargins(15)一样容易。

extension UILabel {
    func setMargins(_ margin: CGFloat = 10) {
        if let textString = self.text {
            var paragraphStyle = NSMutableParagraphStyle()
            paragraphStyle.firstLineHeadIndent = margin
            paragraphStyle.headIndent = margin
            paragraphStyle.tailIndent = -margin
            let attributedString = NSMutableAttributedString(string: textString)
            attributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: attributedString.length))
            attributedText = attributedString
        }
    }
}

答案 31 :(得分:0)

我的解决方案类似于人们的回答,但是添加了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
}
}

答案 32 :(得分:0)

UILabel,在 Swift 5,XCode 11 中,顶部,底部,左侧或右侧具有填充。 Fattie的The great answer经过一些改进后转换为Swift 5。

import UIKit

enum PaddingLabelSpace {
    case none

    case topBy4
    case topBy8
    case topBy16
    case topBy24
    case topBy32

    case bottomBy4
    case bottomBy8
    case bottomBy16
    case bottomBy24
    case bottomBy32

    case spaceBy4
    case spaceBy8
    case spaceBy16
    case spaceBy24
    case spaceBy32

    case spaceVerticallyBy4
    case spaceVerticallyBy8
    case spaceVerticallyBy16
    case spaceVerticallyBy24
    case spaceVerticallyBy32

    case spaceHorizontallyBy4
    case spaceHorizontallyBy8
    case spaceHorizontallyBy16
    case spaceHorizontallyBy24
    case spaceHorizontallyBy32

}

extension PaddingLabelSpace {
    var padding: UIEdgeInsets {
        switch self {
        case .none: return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        case .spaceVerticallyBy4: return UIEdgeInsets(top: 0, left: 4, bottom: 0, right: 4)
        case .spaceVerticallyBy8: return UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 8)
        case .spaceVerticallyBy16: return UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
        case .spaceVerticallyBy24: return UIEdgeInsets(top: 0, left: 24, bottom: 0, right: 24)
        case .spaceVerticallyBy32: return UIEdgeInsets(top: 0, left: 32, bottom: 0, right: 32)

        case .spaceHorizontallyBy4: return UIEdgeInsets(top: 4, left: 0, bottom: 4, right: 0)
        case .spaceHorizontallyBy8: return UIEdgeInsets(top: 8, left: 0, bottom: 8, right: 0)
        case .spaceHorizontallyBy16: return UIEdgeInsets(top: 16, left: 0, bottom: 16, right: 0)
        case .spaceHorizontallyBy24: return UIEdgeInsets(top: 24, left: 0, bottom: 24, right: 0)
        case .spaceHorizontallyBy32: return UIEdgeInsets(top: 32, left: 0, bottom: 32, right: 0)

        case .spaceBy4: return UIEdgeInsets(top: 4, left: 4, bottom: 4, right: 4)
        case .spaceBy8: return UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
        case .spaceBy16: return UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
        case .spaceBy24: return UIEdgeInsets(top: 24, left: 24, bottom: 24, right: 24)
        case .spaceBy32: return UIEdgeInsets(top: 32, left: 32, bottom: 32, right: 32)

        case .topBy4: return UIEdgeInsets(top: 4, left: 0, bottom: 0, right: 0)
        case .topBy8: return UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0)
        case .topBy16: return UIEdgeInsets(top: 16, left: 0, bottom: 0, right: 0)
        case .topBy24: return UIEdgeInsets(top: 24, left: 0, bottom: 0, right: 0)
        case .topBy32: return UIEdgeInsets(top: 32, left: 0, bottom: 0, right: 0)

        case .bottomBy4: return UIEdgeInsets(top: 0, left: 0, bottom: 4, right: 0)
        case .bottomBy8: return UIEdgeInsets(top: 0, left: 0, bottom: 8, right: 0)
        case .bottomBy16: return UIEdgeInsets(top: 0, left: 0, bottom: 16, right: 0)
        case .bottomBy24: return UIEdgeInsets(top: 0, left: 0, bottom: 24, right: 0)
        case .bottomBy32: return UIEdgeInsets(top: 0, left: 0, bottom: 32, right: 0)
        }
    }
}

class PaddingLabel: UILabel {

    var topInset: CGFloat = 0.0
    var bottomInset: CGFloat = 0.0
    var leftInset: CGFloat = 16.0
    var rightInset: CGFloat = 16.0

    override var intrinsicContentSize:CGSize {
        numberOfLines = 0       // don't forget!
        var s = super.intrinsicContentSize
        s.height = s.height + topInset + bottomInset
        return s
    }

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

    override func textRect(forBounds bounds:CGRect,
                               limitedToNumberOfLines n:Int) -> CGRect {
        let b = bounds
        let tr = b.inset(by: UIEdgeInsets(top: topInset, left: leftInset, bottom: bottomInset, right: rightInset))
        let ctr = super.textRect(forBounds: tr, limitedToNumberOfLines: 0)
        return ctr
    }

    func setPadding(paddingSpace: PaddingLabelSpace){
        self.topInset = paddingSpace.padding.top
        self.bottomInset = paddingSpace.padding.bottom
        self.leftInset = paddingSpace.padding.left
        self.rightInset = paddingSpace.padding.right
        let insets: UIEdgeInsets = UIEdgeInsets(top: paddingSpace.padding.top, left: paddingSpace.padding.left, bottom: paddingSpace.padding.bottom, right: paddingSpace.padding.right)

        super.drawText(in: self.frame.inset(by: insets))
    }

    func setPadding(paddingWithEdgeInsets: UIEdgeInsets){
        self.topInset = paddingWithEdgeInsets.top
        self.bottomInset = paddingWithEdgeInsets.bottom
        self.leftInset = paddingWithEdgeInsets.left
        self.rightInset = paddingWithEdgeInsets.right
        let insets: UIEdgeInsets = paddingWithEdgeInsets

        super.drawText(in: self.frame.inset(by: insets))
    }
}

使用方法:

1)将您的IBOutlet设置为PaddingLabel

@IBOutlet weak var userBioLabel: PaddingLabel!

2)设置填充

self.userBioLabel.setPadding(paddingSpace: .spaceVerticallyBy16)

    let UIEI = UIEdgeInsets(top: 3, left: 9, bottom: 3, right: 9)
    self.userBioLabel.setPadding(paddingWithEdgeInsets: UIEI)

答案 33 :(得分:0)

轻松填充

import UIKit

    class NewLabel: UILabel {

        override func textRectForBounds(bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {

            return CGRectInset(self.bounds, CGFloat(15.0), CGFloat(15.0))
        }

        override func drawRect(rect: CGRect) {

            super.drawTextInRect(CGRectInset(self.bounds,CGFloat(5.0), CGFloat(5.0)))
        }

    }

答案 34 :(得分:-1)

雨燕5

在方法layoutSubviews()上,将UILabel的插入内容更改为以下行。

  override func layoutSubviews() {
    super.layoutSubviews()

    label.frame = label.frame.inset(by: UIEdgeInsets(top: 5, left: 10, bottom: 5, right: 10))
  }

答案 35 :(得分:-1)

快速4 +

contentType: "application/x-www-form-urlencoded"

答案 36 :(得分:-4)

如果您只需要左右填充,则只需在文本前后添加空白即可。

titleLabel.text = " \(categoryName) "

enter image description here

enter image description here

enter image description here