向UILabel添加左/右水平填充


67

我需要创建一个UILabel具有背景色的,我想添加一些左/右前/后水平填充。

但是我发现的每个解决方案似乎都是一个讨厌的黑客。

从iOS 5开始实现此目标的“标准”方法是什么?

屏幕截图说明了我的情况:

需要左填充


为什么不把标签的尺寸为特定值,和文本的对齐方式设置为右对齐..?
谢尔盖Kalinichenko

为什么不仅使用CGRectMake(10,y,width,height)创建标签?
incmiko

3
谢谢,附上截图来说明我的问题。我希望标签背景能填满所有宽度,但是我需要将其左对齐。当然,我可以在下面用该颜色添加一个视图,但是我想知道为什么如果没有办法在文本中添加填充,为什么标签会使用背景色。
ssantos

@incmiko,如果我的标签rect从10开始,那么深绿色的背景也会出现。
ssantos

对于最新的太空竞赛,您可以在其前面加上空白字符,例如标准ASCII空格,甚至宽的UNICODE空格(例如“ EM QUAD”)或非常狭窄的“ THIN SPACE”或“ HAIR”空间”。请参阅下面的我的答案,其中包括一个相当全面的UNICODE空间表。
2015年

Answers:


95

有关可用解决方案的完整列表,请参见以下答案:UILabel文本边距


尝试子类化UILabel,就像@Tommy Herbert在[此问题] [1]的答案中建议的那样。复制并粘贴以方便您:

我通过子类化UILabel并重写drawTextInRect来解决此问题:

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

3
此方法返回void,因此该方法结尾不应有任何返回;)仍然有效。
Tomasz Szulc 2014年

如果您想再悬挂一个子类,这是一个很好的解决方案。尽管它具有最佳的灵活性和可重用性,但对于大多数人所需的东西似乎有点混乱和过大。人们可能不知道UNICODE提供了大量的各种宽度的空间,并且可以容纳许多常见场景的填充,而不会导致基于代码的解决方案。请参阅我的答案以获取有关该方法的更多信息。
clearlight'2

1
@ Allaboutthatbase2如果您需要底部和/或顶部填充,我认为Unicode字符不会有所帮助。因此,即使您不想在任何地方重复自己的问题,即使您的解决方案仍然需要一个基于代码的解决方案,您需要集中这种行为。
florian 2015年

@florian-显然不是每种情况的理想选择。但是在很多情况下,这可以节省很多时间,尤其是在制作原型时。作为一个精通图形复杂性,贝塞尔曲线绘制,图像过滤和处理以及字体操纵并创建自己的字体的人,我可以说,我完全感谢您的发言。
2015年

1
对于斯威夫特4.x中,使用super.drawText(in: rect.inset(by: paddingInsets))
parag

27

最重要的部分是您必须同时覆盖intrinsicContentSize()drawTextInRect()以便考虑自动版式:

var contentInset: UIEdgeInsets = .zero {
    didSet {
        setNeedsDisplay()
    }
}

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

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

24

在字符串中也添加一个空格字符。那是可怜的人的填充物:)

要么

我会使用自定义背景视图,但如果您不希望这样做,那么空间是我看到的唯一其他简单选择...

或写一个自定义标签。通过coretext渲染文本


23
#define PADDING 5

@interface MyLabel : UILabel

@end

@implementation MyLabel

- (void)drawTextInRect:(CGRect)rect {
    return [super drawTextInRect:UIEdgeInsetsInsetRect(rect, UIEdgeInsetsMake(0, PADDING, 0, PADDING))];
}

- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines
{
    return CGRectInset([self.attributedText boundingRectWithSize:CGSizeMake(999, 999)
                                                         options:NSStringDrawingUsesLineFragmentOrigin
                                                         context:nil], -PADDING, 0);
}

@end

5
除了子类化UILabel之外,还有其他解决方案吗?
BSKANIA 2014年

16
UIView* bg = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width, 70)];
bg.backgroundColor = [UIColor blackColor];
UILabel* yourLabel = [[UILabel alloc]initWithFrame:CGRectMake(10, y, yourWidth, yourHeight)];
[bg addSubview:yourLabel];

[self addSubview:bg];

16

有时在原型制作时使用UNICODE部分空间来实现对齐是很方便的。这可以方便地进行原型设计,概念验证,或者只是推迟图形算法的实现。

如果您使用UNICODE空格是为了方便起见,请注意,至少UNICODE空格的大小取决于所显示的字体,特别是实际空格字符本身(U + 0020,ASCII 32)

如果您在UILabel中使用默认的iOS系统字体,则默认的System字体特征可能会在后续的iOS版本中更改,并通过更改应用程序的精确间距而突然引入不必要的未对齐现象。这可以并且确实发生,例如,“ San Francisco”字体替换了iOS版本中以前的iOS系统字体。

易于在Swift中指定的UNICODE,例如:

let six_per_em_space = "\u{2006}"

或者,将HTML页面中的空间直接剪切/粘贴到Interface Builder中的UILabel的文本字段中。

注意:随附的图片是屏幕截图,而不是HTML,因此,如果要剪切/粘贴空格,请访问链接的页面

UNICODE空间


5

我在这里的答案有几个问题,例如当您添加填充时,内容的宽度溢出了框,我想要一些角半径。我使用以下UILabel子类解决了此问题:

#import "MyLabel.h"

#define PADDING 8.0
#define CORNER_RADIUS 4.0

@implementation MyLabel

- (void)drawRect:(CGRect)rect {
 self.layer.masksToBounds = YES;
 self.layer.cornerRadius = CORNER_RADIUS;
 UIEdgeInsets insets = {0, PADDING, 0, PADDING};
 return [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
}
- (CGSize) intrinsicContentSize {
 CGSize intrinsicSuperViewContentSize = [super intrinsicContentSize] ;
 intrinsicSuperViewContentSize.width += PADDING * 2 ;
 return intrinsicSuperViewContentSize ;
}

@end

希望对某人有帮助!请注意,如果要在顶部和底部填充,则需要更改以下行:

UIEdgeInsets insets = {0, PADDING, 0, PADDING};

对此:

UIEdgeInsets insets = {PADDING, PADDING, PADDING, PADDING};

并将此行添加到类似的宽度下面:

intrinsicSuperViewContentSize.height += PADDING * 2 ;

4

迅捷5

创建以下课程文件,并通过情节提要将其设置为您的标签作为自定义课程名称。而已。

class PaddingLabel: UILabel {

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


2

我克服此问题的一件事是使用UIButton而不是UILabel。然后,在“界面生成器”的“属性”检查器中,将“标题的边缘”用作填充。
如果未将按钮附加到动作,则单击时不会选择该按钮,但仍将突出显示该按钮。

您还可以使用以下代码以编程方式执行此操作:

UIButton *mButton = [[UIButton alloc] init];
[mButton setTitleEdgeInsets:UIEdgeInsetsMake(top, left, bottom, right)];
[mButton setTitle:@"Title" forState:UIControlStateNormal];
[self.view addSubView:mButton];

这种方法给出了相同的结果,但是有时由于某些原因我没有进行调查,因此无法使用,因为如果可能的话,我会使用Interface Builder。

这仍然是一种解决方法,但如果突出显示不会打扰您,则效果很好。希望它有用


1
不得将aUIButton用作UILabel;这些具有完全不同的用例,并且具有不同的功能集。
Zorayr

1

子类化UILabel并drawTextInRect:像这样重写:

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

0

使用CocoaPods安装

pod 'PaddingLabel', '1.2'

将您的UILabel类更改为PaddingLabel ###例

指定填充

在此处输入图片说明


-1

如果您需要更具体的文本对齐方式,而不是在文本左侧添加空格所提供的对齐方式,则始终可以添加第二个空白标签,以精确显示所需的缩进量。

我的按钮的文本向左对齐,缩进量为10px,并且需要下面的标签才能对齐。它给标签加上了文本和左对齐,然后将其放在x = 10处,然后制作了一个具有相同背景色的小第二个标签,其宽度为10,并将其与实际标签对齐。

最少的代码,看起来不错。只是使AutoLayout变得更加麻烦即可使所有工作正常进行。


如果要在现有标签的左侧添加第二个空白标签,则最好覆盖sizeThatFits或使用自动布局。
Zorayr
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.