如何在UILabel中添加内嵌效果(iOS Swift)?

20

我是一名Android开发者,正在学习iOS。如何在iOS Swift中给UILabel添加填充(内部留白)?我没有找到一个简单易懂的教程。谢谢。

此外,我如何在Swift中给UI元素添加边距?当我尝试下面的代码后,在“添加约束”后没有任何更新。

进入图像描述


请发布您尝试过的代码片段,这样您就能快速解决问题! - Nomesh DeSilva
7个回答

41

这是你需要在 Swift 3 中添加的代码:

class InsetLabel: UILabel {
    let topInset = CGFloat(0)
    let bottomInset = CGFloat(0)
    let leftInset = CGFloat(20)
    let rightInset = CGFloat(20)

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

当您将此子类添加到UIStackView中时,有时会在控制台中出现以下警告:“正在使用超出内部限制的常量配置此NSLayoutConstraint。将替换为较小的值,但应解决此问题。断点BOOL _NSLayoutConstraintNumberExceedsLimit(void)以进行调试。这只会记录一次。请谨慎使用。 - Bart van Kuik
我希望有一种方法可以在不使用子类化的情况下完成这个任务。我目前正在开发一个项目,该项目能够使用一些预定义的样式来为应用程序中的所有UILabel添加样式,但它不支持子类化的UILabel。也许这就是解决我的问题的方法... - Chucky

25

可能最好的方法是继承 UILabel 类并覆盖 drawTextInRect: 方法,就像这样:

class InsetLabel: UILabel {
    override func drawTextInRect(rect: CGRect) {
        super.drawTextInRect(UIEdgeInsetsInsetRect(rect, UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)))
    }
}

SWIFT 4+:

class InsetLabel: UILabel {
    override func drawText(in rect: CGRect) {
        super.drawText(in: rect.inset(by: UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)))
    }
}

我是Swift的新手。我该如何使用它?我对Swift和iOS都不熟悉。@Sebyddd - andyjslee
@andy7586 - 我更新了答案。不要将类的标签设置为“UILabel”,而是设置为“InsetLabel”类。在您的.swift文件中的某个位置添加此类实现。 - Sebyddd
还有一个问题,我如何为任何UI元素添加边距?当我尝试手动设置(请参见更新的问题)时,没有任何更新。 - andyjslee
2
现在文本被截断了。它被截短了。@Sebyddd - andyjslee
@andy7586,那是因为他需要使用intrinsicContentSize - keji
显示剩余2条评论

9

需要添加此内容:

class InsetLabel: UILabel {
let topInset = CGFloat(12.0), bottomInset = CGFloat(12.0), leftInset = CGFloat(12.0), rightInset = CGFloat(12.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
}
}

3
使用故事板很简单就可以解决问题。在故事板中创建一个UIView对象,它的作用是包围标签以便于为其添加填充。然后,也在故事板中将UILabel放置在该视图内部。现在选择UILabel对象并通过点击"Pin"图标打开添加新约束弹出窗口。如果你想要UILabel周围有5个填充,请在添加新约束弹出窗口中点击4个红色I形梁,并在I形梁相邻的4个框中输入5。如果你先输入5,然后再点击一个I形梁,XCode会恢复到你输入5之前的值。最后点击添加约束按钮即可。
在添加约束弹出窗口中,XCode会忽略你没有点击相应的红色I形梁的顶部、左侧、右侧或底部约束值。这大概回答了你问题的第二部分。
还记得设置你添加的UIView的约束条件。如果你没有在故事板中定义它的位置(例如,固定在视图控制器的主视图的顶部和左侧),它将不会被指定默认位置,当你运行应用时可能根本不会出现。

1
迄今为止最佳解决方案 - thibaut noah
这个方法本来是可行的,但如果标签上使用了sizeToFit()方法,那么标签和视图就会相互依赖,什么也不会发生。 - Tilo Delau

3

我已经在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.init(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'


0

另一种方法是重写textRect:forBounds:limitedToNumberOfLines:

返回标签文本的绘制矩形。在需要在系统执行其他文本布局计算之前发生标签边界矩形更改的子类中覆盖此方法。使用numberOfLines参数中的值将返回的矩形高度限制为指定行数的文本。如果先前调用了sizeToFit()或sizeThatFits(_:)方法,则系统可能会调用此方法。请注意,UITableViewCell对象中的标签是基于单元格尺寸而不是请求的尺寸进行调整的。

public class JPSLabel : UILabel
{
    open var textInsets: UIEdgeInsets = UIEdgeInsets.zero

    override public func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect
    {
        var insetBounds = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
        insetBounds.size.width += self.textInsets.left + self.textInsets.right
        insetBounds.size.height += self.textInsets.top + self.textInsets.bottom

        return insetBounds
    }
}

0

我已经在我的应用程序中测试了以下代码,使用的是Swift 5.0 +

class CustomLabel: 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))
    }
}

如何在标签上使用它,请同时提及其用法。 - iPhone 7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接