我想设置一个UILabel的左插图/边距,但找不到这样做的方法。标签有一个背景集,所以仅仅改变它的原点是行不通的。这将是理想的插入文本10px左右在左手边。


当前回答

如果是单行,只需在左侧添加空格,超过一行的填充将再次为0。

[self.myLabel setText:[NSString stringWithFormat:@"   %@", self.myShortString]];

其他回答

对于这样一个简单的情况,子类化有点麻烦。另一种方法是将没有背景设置的UILabel添加到有背景设置的UIView中。将标签的x设置为10,并使外部视图的大小比标签宽20个像素。

我通过子类化UILabel和重写drawTextInRect来解决这个问题:

- (void)drawTextInRect:(CGRect)rect {
    UIEdgeInsets insets = {0, 5, 0, 5};
    [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
}

斯威夫特3.1:

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

斯威夫特4.2.1:准备

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

你可能已经猜到了,这是对tc的改编。的答案。它有两个优点:

没有必要通过发送sizeToFit消息来触发它 它只保留标签框架——如果你的标签有背景,而你不想让它缩小,这很方便

回收钢铁的答案的Swift版本+ intrinsizeContentSize()。

它支持一个更传统的设置insets为其他视图对象的insets,同时能够设置insets在接口生成器,即insets设置像这样编程:

label.insets = UIEdgeInsetsMake(0, 0, 5, 0)

如果有任何错误,请告诉我。

斯威夫特5

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

var insets: UIEdgeInsets {
    get {
        return UIEdgeInsets(top: topInset, left: leftInset, bottom: bottomInset, right: rightInset)
    }
    set {
        topInset = newValue.top
        leftInset = newValue.left
        bottomInset = newValue.bottom
        rightInset = newValue.right
    }
}

override func drawText(in rect: CGRect) {
    super.drawText(in: UIEdgeInsetsInsetRect(rect, insets))
}

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 {
    var contentSize = super.intrinsicContentSize
    contentSize.width += leftInset + rightInset
    contentSize.height += topInset + bottomInset
    
    return contentSize
}

斯威夫特4.2

@IBDesignable class InsetLabel: UILabel {
    @IBInspectable var topInset: CGFloat = 0.0
    @IBInspectable var leftInset: CGFloat = 0.0
    @IBInspectable var bottomInset: CGFloat = 0.0
    @IBInspectable var rightInset: CGFloat = 0.0
    
    var insets: UIEdgeInsets {
        get {
            return UIEdgeInsetsMake(topInset, leftInset, bottomInset, rightInset)
        }
        set {
            topInset = newValue.top
            leftInset = newValue.left
            bottomInset = newValue.bottom
            rightInset = newValue.right
        }
    }
    
    override func drawText(in rect: CGRect) {
        super.drawText(in: rect.inset(by: insets))
    }
    
    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 {
        var contentSize = super.intrinsicContentSize
        contentSize.width += leftInset + rightInset
        contentSize.height += topInset + bottomInset
        
        return contentSize
    }
}

斯威夫特3

@IBDesignable class InsetLabel: UILabel {
    @IBInspectable var topInset: CGFloat = 0.0
    @IBInspectable var leftInset: CGFloat = 0.0
    @IBInspectable var bottomInset: CGFloat = 0.0
    @IBInspectable var rightInset: CGFloat = 0.0
    
    var insets: UIEdgeInsets {
        get {
            return UIEdgeInsetsMake(topInset, leftInset, bottomInset, rightInset)
        }
        set {
            topInset = newValue.top
            leftInset = newValue.left
            bottomInset = newValue.bottom
            rightInset = newValue.right
        }
    }
    
    override func drawText(in rect: CGRect) {
        super.drawText(in: UIEdgeInsetsInsetRect(rect, insets))
    }
    
    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 {
        var contentSize = super.intrinsicContentSize
        contentSize.width += leftInset + rightInset
        contentSize.height += topInset + bottomInset
        
        return contentSize
    }
}

斯威夫特2.2

@IBDesignable class InsetLabel: UILabel {
    @IBInspectable var topInset: CGFloat = 0.0
    @IBInspectable var leftInset: CGFloat = 0.0
    @IBInspectable var bottomInset: CGFloat = 0.0
    @IBInspectable var rightInset: CGFloat = 0.0
    
    var insets: UIEdgeInsets {
        get {
            return UIEdgeInsetsMake(topInset, leftInset, bottomInset, rightInset)
        }
        set {
            topInset = newValue.top
            leftInset = newValue.left
            bottomInset = newValue.bottom
            rightInset = newValue.right
        }
    }
        
    override func drawTextInRect(rect: CGRect) {
        super.drawTextInRect(UIEdgeInsetsInsetRect(rect, insets))
    }
        
    override func sizeThatFits(size: CGSize) -> CGSize {
        var adjSize = super.sizeThatFits(size)
        adjSize.width += leftInset + rightInset
        adjSize.height += topInset + bottomInset
        
        return adjSize
    }
    
    override func intrinsicContentSize() -> CGSize {
        var contentSize = super.intrinsicContentSize()
        contentSize.width += leftInset + rightInset
        contentSize.height += topInset + bottomInset
        
        return contentSize
    }
}

对于多行文本,可以使用NSAttributedString设置左右边距。

NSMutableParagraphStyle *style =  [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
style.alignment = NSTextAlignmentJustified;
style.firstLineHeadIndent = 10.0f;
style.headIndent = 10.0f;
style.tailIndent = -10.0f;   

NSAttributedString *attrText = [[NSAttributedString alloc] initWithString:title attributes:@{ NSParagraphStyleAttributeName : style}];  

UILabel * label = [[UILabel alloc] initWithFrame:someFrame];
label.numberOfLines = 0;
label.attributedText = attrText;

以下是Swift 5采用的上述示例:

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

如果你不想使用一个额外的父视图来设置背景,你可以子类化UILabel并重写textRectForBounds: limitedtonumberolines:。我会添加一个textEdgeInsets属性或类似的,然后做

- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines
{
  return [super textRectForBounds:UIEdgeInsetsInsetRect(bounds,textEdgeInsets) limitedToNumberOfLines:numberOfLines];
}

为了健壮性,你可能还想在setTextEdgeInsets:中调用[self setNeedsDisplay],但我通常不这么做。