关于ios:UILabel文字边距

UILabel text margin

我想要设置UILabel的左插图/边距,但找不到找到该方法的方法。 标签具有背景设置,因此仅更改其来源就不会成功。 最好在左侧用10px插入文本。


我通过子类化UILabel并覆盖drawTextInRect:来解决此问题,如下所示:

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

Swift 3.1:

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

Swift 4.2.1:

1
2
3
4
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消息来触发它
  • 它使标签框保持独立状态-如果标签有背景并且您不希望其收缩,则非常方便

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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;


    向UILabel添加填充的最佳方法是子类UILabel并添加edgeInsets属性。然后设置所需的插图,标签将相应绘制。

    OSLabel.h

    1
    2
    3
    4
    5
    6
    7
    #import <UIKit/UIKit.h>

    @interface OSLabel : UILabel

    @property (nonatomic, assign) UIEdgeInsets edgeInsets;

    @end

    OSLabel.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #import"OSLabel.h"

    @implementation OSLabel

    - (id)initWithFrame:(CGRect)frame{
        self = [super initWithFrame:frame];
        if (self) {
            self.edgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
        }
        return self;
    }

    - (void)drawTextInRect:(CGRect)rect {
        [super drawTextInRect:UIEdgeInsetsInsetRect(rect, self.edgeInsets)];
    }

    - (CGSize)intrinsicContentSize
    {
        CGSize size = [super intrinsicContentSize];
        size.width  += self.edgeInsets.left + self.edgeInsets.right;
        size.height += self.edgeInsets.top + self.edgeInsets.bottom;
        return size;
    }

    @end


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


    我最后只是在文本中添加了一些空格:

    1
    self.titleLabel.text = [NSString stringWithFormat:@"    %@", self.titleLabel.text];

    丑陋但有效,不需要子类化。

    您也可以尝试" t"。有关通用解决方案,请参阅接受的答案


    使用Swift 3,您可以通过创建UILabel的子类来获得所需的效果。在此子类中,您将必须添加带有必需插入物的UIEdgeInsets属性,并覆盖drawText(in:)方法,intrinsicContentSize属性(对于自动布局代码)和/或sizeThatFits(_:)方法(对于Springs&Struts代码)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    import UIKit

    class PaddingLabel: UILabel {

        let padding: UIEdgeInsets

        // Create a new PaddingLabel instance programamtically with the desired insets
        required init(padding: UIEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)) {
            self.padding = padding
            super.init(frame: CGRect.zero)
        }

        // Create a new PaddingLabel instance programamtically with default insets
        override init(frame: CGRect) {
            padding = UIEdgeInsets.zero // set desired insets value according to your needs
            super.init(frame: frame)
        }

        // Create a new PaddingLabel instance from Storyboard with default insets
        required init?(coder aDecoder: NSCoder) {
            padding = UIEdgeInsets.zero // set desired insets value according to your needs
            super.init(coder: aDecoder)
        }

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

        // Override `intrinsicContentSize` property for Auto layout code
        override var intrinsicContentSize: CGSize {
            let superContentSize = super.intrinsicContentSize
            let width = superContentSize.width + padding.left + padding.right
            let heigth = superContentSize.height + padding.top + padding.bottom
            return CGSize(width: width, height: heigth)
        }

        // Override `sizeThatFits(_:)` method for Springs & Struts code
        override func sizeThatFits(_ size: CGSize) -> CGSize {
            let superSizeThatFits = super.sizeThatFits(size)
            let width = superSizeThatFits.width + padding.left + padding.right
            let heigth = superSizeThatFits.height + padding.top + padding.bottom
            return CGSize(width: width, height: heigth)
        }

    }

    以下示例显示如何在UIViewController中使用PaddingLabel实例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    import UIKit

    class ViewController: UIViewController {

        @IBOutlet weak var storyboardAutoLayoutLabel: PaddingLabel!
        let autoLayoutLabel = PaddingLabel(padding: UIEdgeInsets(top: 20, left: 40, bottom: 20, right: 40))
        let springsAndStructsLabel = PaddingLabel(frame: CGRect.zero)
        var textToDisplay ="Lorem ipsum dolor sit er elit lamet."

        override func viewDidLoad() {
            super.viewDidLoad()

            // Set autoLayoutLabel
            autoLayoutLabel.text = textToDisplay
            autoLayoutLabel.backgroundColor = .red
            autoLayoutLabel.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(autoLayoutLabel)
            autoLayoutLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
            autoLayoutLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

            // Set springsAndStructsLabel
            springsAndStructsLabel.text = textToDisplay
            springsAndStructsLabel.backgroundColor = .green
            view.addSubview(springsAndStructsLabel)
            springsAndStructsLabel.frame.origin = CGPoint(x: 30, y: 90)
            springsAndStructsLabel.sizeToFit()

            // Set storyboardAutoLayoutLabel
            storyboardAutoLayoutLabel.text = textToDisplay
            storyboardAutoLayoutLabel.backgroundColor = .blue
        }

        // Link this IBAction to a UIButton or a UIBarButtonItem in Storyboard
        @IBAction func updateLabelText(_ sender: Any) {
            textToDisplay = textToDisplay =="Lorem ipsum dolor sit er elit lamet." ?"Lorem ipsum." :"Lorem ipsum dolor sit er elit lamet."

            // autoLayoutLabel
            autoLayoutLabel.text = textToDisplay

            // springsAndStructsLabel
            springsAndStructsLabel.text = textToDisplay
            springsAndStructsLabel.sizeToFit()

            // storyboardAutoLayoutLabel
            storyboardAutoLayoutLabel.text = textToDisplay
        }

    }


    Swift版本的Recycled Steel的答案+ intrinsizeContentSize()

    它支持一种更传统的样式,即可以在Interface Builder中设置带有嵌入的其他视图对象的嵌入,同时也可以通过编程方式设置嵌入:

    1
    label.inset = UIEdgeInsetsMake(0, 0, 5, 0)

    请让我知道是否有任何错误。

    迅捷3

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    @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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    @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
        }
    }


    您也可以通过使用自定义框架初始化UILabel来解决此问题。

    1
    2
    3
    4
    5
        CGRect initialFrame = CGRectMake(0, 0, 100, 100);
        UIEdgeInsets contentInsets = UIEdgeInsetsMake(0, 10, 0, 0);
        CGRect paddedFrame = UIEdgeInsetsInsetRect(initialFrame, contentInsets);

        self.label = [[UILabel alloc] initWithFrame:paddedFrame];

    向CGRect技巧致敬。


    对于Xamarin用户(使用Unified API):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class UIMarginLabel : UILabel
    {
        public UIMarginLabel()
        {
        }

        public UIMarginLabel( CGRect frame ) : base( frame )
        {
        }

        public UIEdgeInsets Insets { get; set; }

        public override void DrawText( CGRect rect )
        {
            base.DrawText( Insets.InsetRect( rect ) );
        }
    }

    对于使用原始MonoTouch API的用户:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class UIMarginLabel : UILabel
    {
        public UIEdgeInsets Insets { get; set; }

        public UIMarginLabel() : base()
        {
            Insets = new UIEdgeInsets(0, 0, 0, 0);
        }
        public UIMarginLabel(RectangleF frame) : base(frame)
        {
            Insets = new UIEdgeInsets(0, 0, 0, 0);
        }

        public override void DrawText(RectangleF frame)
        {
            base.DrawText(new RectangleF(
                frame.X + Insets.Left,
                frame.Y + Insets.Top,
                frame.Width - Insets.Left - Insets.Right,
                frame.Height - Insets.Top - Insets.Bottom));
        }
    }


    和@IBDesignable使其可以与Interface Builder一起使用

    斯威夫特4

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    //
    //  PaddedLabel.swift
    //  TrainCentric
    //
    //  Created by Arsonik
    //  https://stackoverflow.com/a/33244365/337934
    //

    import UIKit

    @IBDesignable
    class PaddedLabel: UILabel {

        @IBInspectable var inset:CGSize = CGSize(width: 0, height: 0)

        var padding: UIEdgeInsets {
            var hasText:Bool = false
            if let t = self.text?.count, t > 0 {
                hasText = true
            }
            else if let t = attributedText?.length, t > 0 {
                hasText = true
            }

            return hasText ? UIEdgeInsets(top: inset.height, left: inset.width, bottom: inset.height, right: inset.width) : UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        }

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

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

        override func sizeThatFits(_ size: CGSize) -> CGSize {
            let superSizeThatFits = super.sizeThatFits(size)
            let p = padding
            let width = superSizeThatFits.width + p.left + p.right
            let heigth = superSizeThatFits.height + p.top + p.bottom
            return CGSize(width: width, height: heigth)
        }
    }

    迅捷2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    @IBDesignable
    class PaddedLabel: UILabel {

        @IBInspectable var inset:CGSize = CGSize(width: 0, height: 0)

        var padding: UIEdgeInsets {
            var hasText:Bool = false
            if let t = text?.length where t > 0 {
                hasText = true
            }
            else if let t = attributedText?.length where t > 0 {
                hasText = true
            }

            return hasText ? UIEdgeInsets(top: inset.height, left: inset.width, bottom: inset.height, right: inset.width) : UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        }

        override func drawTextInRect(rect: CGRect) {
            super.drawTextInRect(UIEdgeInsetsInsetRect(rect, padding))
        }

        override func intrinsicContentSize() -> CGSize {
            let superContentSize = super.intrinsicContentSize()
            let p = padding
            let width = superContentSize.width + p.left + p.right
            let heigth = superContentSize.height + p.top + p.bottom
            return CGSize(width: width, height: heigth)
        }

        override func sizeThatFits(size: CGSize) -> CGSize {
            let superSizeThatFits = super.sizeThatFits(size)
            let p = padding
            let width = superSizeThatFits.width + p.left + p.right
            let heigth = superSizeThatFits.height + p.top + p.bottom
            return CGSize(width: width, height: heigth)
        }
    }

    要扩展Brody Robertson提供的答案,您可以添加IB Designable位。这意味着您可以在情节提要中调整标签。

    enter image description here

    在子类化的UILabel中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #import <UIKit/UIKit.h>

    IB_DESIGNABLE

    @interface insetLabel : UILabel

    @property (nonatomic, assign) IBInspectable CGFloat leftEdge;
    @property (nonatomic, assign) IBInspectable CGFloat rightEdge;
    @property (nonatomic, assign) IBInspectable CGFloat topEdge;
    @property (nonatomic, assign) IBInspectable CGFloat bottomEdge;

    @property (nonatomic, assign) UIEdgeInsets edgeInsets;

    @end

    然后做;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    #import"insetLabel.h"

    @implementation insetLabel

    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self)
        {
            self.edgeInsets = UIEdgeInsetsMake(self.topEdge, self.leftEdge, self.bottomEdge, self.rightEdge);
        }
        return self;
    }

    - (void)drawTextInRect:(CGRect)rect
    {
        self.edgeInsets = UIEdgeInsetsMake(self.topEdge, self.leftEdge, self.bottomEdge, self.rightEdge);

        [super drawTextInRect:UIEdgeInsetsInsetRect(rect, self.edgeInsets)];
    }

    - (CGSize)intrinsicContentSize
    {
        CGSize size = [super intrinsicContentSize];
        size.width  += self.edgeInsets.left + self.edgeInsets.right;
        size.height += self.edgeInsets.top + self.edgeInsets.bottom;
        return size;
    }

    @end

    编辑

    您可能应该为edgeInsets添加一个setter方法。


    如果不想使用额外的父视图来设置背景,则可以继承UILabel并覆盖textRectForBounds:limitedToNumberOfLines:。我将添加textEdgeInsets属性或类似属性,然后执行

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

    为了健壮起见,您可能还想在setTextEdgeInsets:中调用[self setNeedsDisplay],但是我通常不会打扰。


    也许稍后再参加聚会,但是下面的方法是可行的。只是子类UILabel。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #import"UITagLabel.h"

    #define padding UIEdgeInsetsMake(5, 10, 5, 10)

    @implementation UITagLabel

    - (void)drawTextInRect:(CGRect)rect {
        [super drawTextInRect:UIEdgeInsetsInsetRect(rect, padding)];
    }

    - (CGSize) intrinsicContentSize {
        CGSize superContentSize = [super intrinsicContentSize];
        CGFloat width = superContentSize.width + padding.left + padding.right;
        CGFloat height = superContentSize.height + padding.top + padding.bottom;
        return CGSizeMake(width, height);
    }

    - (CGSize) sizeThatFits:(CGSize)size {
        CGSize superSizeThatFits = [super sizeThatFits:size];
        CGFloat width = superSizeThatFits.width + padding.left + padding.right;
        CGFloat height = superSizeThatFits.height + padding.top + padding.bottom;
        return CGSizeMake(width, height);
    }

    @end

    如果您在iOS 6+中使用自动布局,则可以通过调整UILabel子类中的intrinsicContentSize来实现。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            self.textAlignment = NSTextAlignmentRight;
        }
        return self;
    }

    - (CGSize)intrinsicContentSize
    {
        CGSize size = [super intrinsicContentSize];
        return CGSizeMake(size.width + 10.0, size.height);
    }


    这是一个快速的解决方案。只需在文件底部添加此自定义类(或为其创建一个新文件),然后在创建标签时使用MyLabel而不是UILabel。

    1
    2
    3
    4
    5
    class MyLabel: UILabel{
        override func drawTextInRect(rect: CGRect) {
            super.drawTextInRect(UIEdgeInsetsInsetRect(rect, UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)))
        }
    }


    在Swift中,它像这样解决。

    1
    2
    3
    4
    5
    class Label: UILabel {
        override func drawTextInRect(rect: CGRect) {
            super.drawTextInRect(UIEdgeInsetsInsetRect(rect, UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)))
        }
    }

    代替UILabel也许使用https://github.com/mattt/TTTAttributedLabel

    1
    2
    3
    4
    5
    BITAttributedLabel *label = [BITAttributedLabel new];
    label.font = font;
    label.text = @"hello";
    label.textInsets = UIEdgeInsetsMake(10, 10, 10, 10);
    [label sizeToFit];

    blyabtroi的asnwer在Swift中转换(无需子类化)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    let style: NSMutableParagraphStyle = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle
    style.alignment = .Justified
    style.firstLineHeadIndent = 10.0
    style.headIndent = 10.0
    style.tailIndent = -10.0
    let attrText: NSAttributedString = NSAttributedString(string: title, attributes: [NSParagraphStyleAttributeName:style])
    let label: UILabel = UILabel(frame: someFrame)
    label.numberOfLines = 0
    label.attributedText = attrText

    许多答案都没有覆盖sizeThatFits。使用此子类,您可以仅创建标签,设置填充,然后说出label.SizeToFit()和voila。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import UIKit

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

        override func drawTextInRect(rect: CGRect) {

            super.drawTextInRect(UIEdgeInsetsInsetRect(rect, padding))
        }

        override func sizeThatFits(size: CGSize) -> CGSize
        {

            var adjSize = super.sizeThatFits(size)
            adjSize.width += padding.left + padding.right
            adjSize.height += padding.top + padding.bottom

            return adjSize
        }
    }


    Swift 4版本的Blyabtroi解决方案

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    let leadingMargin: CGFloat = 10
    let trailingMargin: CGFloat = 10

    let style = NSMutableParagraphStyle()
    style.alignment = .justified
    style.firstLineHeadIndent = leadingMargin
    style.headIndent = leadingMargin
    style.tailIndent = trailingMargin

    label.attributedText = NSAttributedString(string:"Label with margins",
                                              attributes: [NSAttributedStringKey.paragraphStyle: style])

    我没有在上述答案中使用UIButton的建议。因此,我将尝试证明这是一个不错的选择。

    在我的情况下,使用UIButton是最佳解决方案,因为:

    • 我有一个简单的单行文字
    • 我不想将UIView用作UILabel的容器(即,我想简化单元格中自动布局的数学计算)
    • 我不想使用NSParagraphStyle(因为tailIndent在自动布局中无法正常工作-UILabel的宽度小于预期)
    • 我不想使用UITextView(因为可能会有副作用)
    • 我不想继承UILabel(更少的代码,更少的bug)

    这就是为什么在我的情况下使用UIButton中的contentEdgeInsets成为添加文本页边距的最简单方法。

    希望这会帮助某人。


    这适用于多行标签:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class PaddedLabel: UILabel {
        var verticalPadding: CGFloat = 0
        var horizontalPadding: CGFloat = 0

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

        override var intrinsicContentSize: CGSize {
            get {
                let textWidth = super.intrinsicContentSize.width - horizontalPadding * 2
                let textHeight = sizeThatFits(CGSize(width: textWidth, height: .greatestFiniteMagnitude)).height
                let width = textWidth + horizontalPadding * 2
                let height = textHeight + verticalPadding * 2
                return CGSize(width: frame.width, height: height)
            }
        }
    }

    这是我为此找到的最简单的解决方案:

    斯威夫特4

    1
    2
    3
    4
    5
    class CustomLabel: UILabel{
        override func drawText(in rect: CGRect) {
            super.drawText(in: rect.inset(by: UIEdgeInsets.init(top: 10, left: 10, bottom: 10, right: 10)))
        }
    }

    确保在代码和情节提要中将标签设置为CustomLabel类。


    Swift 3和AutoLayout兼容版本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    class InsetLabel: UILabel {

        var insets = UIEdgeInsets()

        convenience init(insets: UIEdgeInsets) {
            self.init(frame: CGRect.zero)
            self.insets = insets
        }

        convenience init(dx: CGFloat, dy: CGFloat) {
            let insets = UIEdgeInsets(top: dy, left: dx, bottom: dy, right: dx)
            self.init(insets: insets)
        }

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

        override var intrinsicContentSize: CGSize  {
            var size = super.intrinsicContentSize
            size.width += insets.left + insets.right
            size.height += insets.top + insets.bottom
            return size
        }
    }


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #import"E_LabelWithPadding.h"
    #define padding UIEdgeInsetsMake(2, 0, 2, 0)
    #define padding1 UIEdgeInsetsMake(0, 0, 0, 0)
    @implementation E_LabelWithPadding
    - (void)drawTextInRect:(CGRect)rect {
    if (![self.text isEqualToString:@""]) {
        [super drawTextInRect:UIEdgeInsetsInsetRect(rect, padding)];
    }else {
        [super drawTextInRect:UIEdgeInsetsInsetRect(rect, padding1)];
    }

    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    - (CGSize) intrinsicContentSize {
    if (![self.text isEqualToString:@""]) {
        CGSize superContentSize = [super intrinsicContentSize];
        CGFloat width = superContentSize.width + padding.left + padding.right;
        CGFloat height = superContentSize.height + padding.top + padding.bottom;
        return CGSizeMake(width, height);
    }else {
        CGSize superContentSize = [super intrinsicContentSize];
        CGFloat width = superContentSize.width + padding1.left + padding1.right;
        CGFloat height = superContentSize.height + padding1.top + padding1.bottom;
        return CGSizeMake(width, height);
    }

    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    - (CGSize) sizeThatFits:(CGSize)size {
    if (![self.text isEqualToString:@""]) {
        CGSize superSizeThatFits = [super sizeThatFits:size];
        CGFloat width = superSizeThatFits.width + padding.left + padding.right;
        CGFloat height = superSizeThatFits.height + padding.top + padding.bottom;
        return CGSizeMake(width, height);
    }else {
        CGSize superSizeThatFits = [super sizeThatFits:size];
        CGFloat width = superSizeThatFits.width + padding1.left + padding1.right;
        CGFloat height = superSizeThatFits.height + padding1.top + padding1.bottom;
        return CGSizeMake(width, height);
    }

    }

    1
    @end

    Xcode 6.1.1使用扩展的Swift解决方案。

    文件名可能类似于" UILabel + AddInsetMargin.swift":

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import UIKit

    extension UILabel
    {
        public override func drawRect(rect: CGRect)
        {
            self.drawTextInRect(UIEdgeInsetsInsetRect(rect, UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)))
        }
    }


    没有子类和所有爵士乐。.我动态地做到了:

    1
    2
    [cell.textLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
    [cell.textLabel constraintTrailingEqualTo:cell.contentView constant:-100];

    约束部分只是一个简单的代码糖包装器(我们有相同的方法从顶部/底部/左侧/右侧添加填充)。如果我在这里得到足够的爱,我将开放整个包装器的源代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    - (id)constraintTrailingEqualTo:(UIView *)toView constant:(CGFloat)constant
    {
        NSLayoutConstraint *cn = [NSLayoutConstraint constraintWithItem:self
                                                              attribute:NSLayoutAttributeTrailing
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:toView
                                                              attribute:NSLayoutAttributeTrailing
                                                             multiplier:1 constant:constant];

        [toView addConstraint:cn];
        return self;
    }

    (请注意,我是在

    1
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath;

    您可能需要根据上下文致电[self setNeedsLayout];


    如果标签是通过编程方式创建的,则可以使用sizeThatFits方法计算填充。如果使用多行,则文本将以最大宽度值换行。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    let text = UILabel()
    let padding = 10
    text.layer.cornerRadius = 5
    text.layer.masksToBounds = true
    text.text ="Hello"
    text.font = UIFont(name: text.font.fontName, size: 18)
    text.textAlignment = NSTextAlignment.center
    text.numberOfLines = 1

    let maxSize = CGSize(width: 100, height: 100)
    var size = text.sizeThatFits(maxSize)
    size.width = size.width + padding * 2
    size.height = size.height + padding * 2
    text.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: size)

    我已经使用xcode生成器解决了它(但是可以肯定的是,使用约束快速实现):

    只需创建一个相关大小的UIView
    并将UILabel类型的子项添加到该视图

    然后你去了,你有填充:)

    xcode builder solution


    也许您可以尝试一下此代码

    1
    2
    3
    4
    CGRect frame = btn.titleLabel.frame;
    int indent = 20;
    int inset = 20;
    [btn.titleLabel setFrame:CGRectMake(frame.origin.x+inset,frame.origin.y,frame.size.width+indent,frame.size.height)];


    为了摆脱单行标签的垂直填充,我这样做了:

    1
    2
    // I have a category method setFrameHeight; you'll likely need to modify the frame.
    [label setFrameHeight:font.pointSize];

    或者,不使用类别,请使用:

    1
    2
    3
    CGRect frame = label.frame;
    frame.size.height = font.pointSize;
    label.frame = frame;

    如果是单行,只需在左侧添加空格,多于1行将再次填充0。

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


    我认为UILabel类没有设置边距的方法。为什么不将Label的位置设置在所需的位置?

    请参阅以下代码:

    1
    2
    3
    UILabel *label = [[UILabel alloc] init];
    label.text = @"This is label";
    label.frame = CGRectMake(0,0,100,100);

    如果来自界面构建器,则只需按照以下步骤放置Label:

    1
    yourLabel.frame = CGRectMake(0,0,100,100);

    插入插图时,需要计算UILabel大小。由于文本对齐,换行模式,它可以具有不同的行数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    override func drawText(in rect: CGRect) {

        let size = self.sizeThatFits(UIEdgeInsetsInsetRect(rect, insets).size);
        super.drawText(in: CGRect.init(origin: CGPoint.init(x: insets.left, y: insets.top), size: size));
    }

    override var intrinsicContentSize: CGSize {

        var size = super.intrinsicContentSize;

        if text == nil || text?.count == 0 {
            return size;
        }

        size = self.sizeThatFits(UIEdgeInsetsInsetRect(CGRect.init(origin: CGPoint.zero, size: size), insets).size);
        size.width  += self.insets.left + self.insets.right;
        size.height += self.insets.top + self.insets.bottom;

        return size;
    }

    试试iEun / InsetLabel


    这是我找到的最简单的方法。对我来说,它就像是一种魅力。

    1
    2
    3
    4
    5
    UIView *titleSection = [[UIView alloc] initWithFrame:CGRectMake(0, 0, screenWidth, 100)];
    [titleSection addSubview:titleSection];

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectInset(titleSection.frame, PADDING, 0)];
    [titleSection addSubview:label];

    这些答案很多都是复杂的。在某些情况下,这是必要的。但是,如果您正在阅读本文,则标签没有左右边距,而您只需要一点填充,这是完整的解决方案:

    第1步:在末尾添加空格(实际上是按几次空格键)

    步骤2:将标签的文本对齐方式设置为居中

    完成


    将标签的textAlignment属性设置为NSTextAlignmentRight并增加其宽度。


    不要编码,Xcode!

    建议您不要使用UILabel来解决此特定问题,而建议您看一下UIButton。它提供了开箱即用的功能,可以在"大小"检查器中设置"内容插入"(顶部,左侧,底部,右侧)。设置所需的边距,然后禁用Xcode中的按钮并完成操作。