向 UILabel 添加左/右水平填充

Posted

技术标签:

【中文标题】向 UILabel 添加左/右水平填充【英文标题】:Add left/right horizontal padding to UILabel 【发布时间】:2013-10-17 21:24:26 【问题描述】:

我需要创建一个带有背景颜色的UILabel,并且我想添加一些左/右前导/尾随水平填充。

但我发现的每一个解决方案似乎都是一个令人讨厌的 hack。

ios 5 开始,实现这一目标的“标准”方式是什么?

一个截图来说明我的场景:

【问题讨论】:

为什么不将标签大小设置为特定值,并将文本对齐设置为右对齐?.. 为什么不使用 CGRectMake(10,y,width,height) 创建标签? 谢谢,附上截图来说明我的问题。我希望标签背景填充所有宽度,但我需要它左对齐。当然我可以在下面添加一个具有该颜色的视图,但我只是想知道如果没有办法为文本添加填充,为什么标签的背景颜色。 @incmiko,如果我的标签 rect 从 10 开始,那么深绿色背景也会。 关于太空竞赛的最新消息......您可以在它前面加上一个空白字符,例如标准 ASCII 空间,甚至是宽的 UNICODE 空间,例如“EM QUAD”或非常窄的一个“薄空间”或“头发空间”。请参阅我的答案,其中包括下面一个相当全面的 UNICODE 空格表。 【参考方案1】:

有关可用解决方案的完整列表,请参阅此答案:UILabel text margin


尝试继承 UILabel,就像 @Tommy Herbert 在 [this question][1] 的答案中建议的那样。为了您的方便,复制并粘贴:

我通过继承 UILabel 并覆盖 drawTextInRect: 解决了这个问题:

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

【讨论】:

此方法返回 void,因此此方法结束时不应有返回 ;) 仍然有效。 如果您还想再拥有一个子类,这是一个很好的解决方案。虽然它具有最佳的灵活性和可重用性,但对于大多数人的需求来说,它似乎有点杂乱和矫枉过正。人们可能不知道 UNICODE 提供了大量各种宽度的空间,并且可以为许多常见场景提供填充,而不会产生基于代码的解决方案。有关该方法的更多信息,请参阅我的回答。 @Allaboutthatbase2 如果您需要底部和/或顶部填充,我认为 Unicode 字符不会有帮助。因此,如果您不想到处重复自己,即使有您的解决方案,您仍然需要一个代码库解决方案,您需要集中这种行为。 @florian - 这显然不是所有情况的理想选择。但在很多情况下,它可以节省大量时间,尤其是在原型设计时。作为一个研究过复杂的图形、贝塞尔曲线绘制、图像过滤和处理以及字体操作并创建了我自己的字体的人,我可以说,我完全理解你所说的。 对于 Swift 4.x,使用 super.drawText(in: rect.inset(by: paddingInsets))【参考方案2】:

最重要的部分是您必须同时覆盖 intrinsicContentSize()drawTextInRect() 才能考虑 AutoLayout:

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

【讨论】:

【参考方案3】:

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

我会使用自定义背景视图,但如果您不想要,空间是我看到的唯一其他简单选项...

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

【讨论】:

【参考方案4】:
#define PADDING 5

@interface MyLabel : UILabel

@end

@implementation MyLabel

- (void)drawTextInRect:(CGRect)rect 
    UIEdgeInsets insets = UIEdgeInsetsMake(0, PADDING, 0, PADDING);
    CGRect rect = UIEdgeInsetsInsetRect(rect, insets);
    return [super drawTextInRect:rect];


- (CGRect)textRectForBounds:(CGRect)bounds
     limitedToNumberOfLines:(NSInteger)numberOfLines

    CGSize size = CGSizeMake(999, 999);
    CGRect rect = [self.attributedText
                   boundingRectWithSize:size
                                options:NSStringDrawingUsesLineFragmentOrigin
                                context:nil];
    return CGRectInset(rect, -PADDING, 0);


@end

【讨论】:

除了子类化 UILabel 还有其他解决方案吗?【参考方案5】:
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];

【讨论】:

【参考方案6】:

有时在原型制作时使用 UNICODE 部分空格来实现对齐很方便。这在原型设计、概念验证或只是推迟图形算法的实现时非常方便。

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

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

在 Swift 中很容易指定 UNICODE,例如:

let six_per_em_space = "\u2006"

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

注意:附图是截图,不是 HTML,如果你想剪切/粘贴空格,请访问linked page。

【讨论】:

【参考方案7】:

我在这里的答案有几个问题,例如当您添加填充时,内容的宽度溢出了框,我想要一些圆角半径。我使用 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 ;

【讨论】:

【参考方案8】:

斯威夫特 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))
    

【讨论】:

在调用方法时我应该在 rect 中传递什么?【参考方案9】:

如果您想为 UILabel 添加填充但不想对其进行子类化,您可以将标签放在 UIView 中并使用自动布局提供填充,例如:

结果:

【讨论】:

【参考方案10】:

我为解决这个问题所做的一件事是使用 UIButton 而不是 UILabel。然后在 Interface Builder 的 Attributes Inspector 中,我使用 Title 的 Edge 作为填充。 如果您不将按钮附加到操作,则单击时将不会被选中,但仍会显示突出显示。

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

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

这种方法给出了相同的结果,但有时由于某种我没有调查的原因它不起作用,因为如果可能的话,我会使用 Interface Builder。

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

【讨论】:

不得将UIButton 用作UILabel;它们具有完全不同的用例,并具有不同的功能集。【参考方案11】:

子类 UILabel 并像这样覆盖drawTextInRect:

- (void)drawTextInRect:(CGRect)rect 

    UIEdgeInsets insets = 0, 10, 0, 0;
    return [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];

【讨论】:

【参考方案12】:

使用 CocoaPods 安装

pod 'PaddingLabel', '1.2'

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

指定填充

【讨论】:

【参考方案13】:

如果您需要比在文本左侧添加空格提供的更具体的文本对齐方式,您可以随时添加第二个空白标签,说明您需要多少缩进。

我的按钮左对齐,缩进为 10 像素,需要在下方添加标签才能对齐。 它为标签提供了文本和左对齐并将其放在 x=10 处,然后制作了一个具有相同背景颜色且宽度 = 10 的第二个小标签,并将其与真实标签对齐。

最少的代码,看起来不错。 只是让 AutoLayout 让一切正常工作变得更加麻烦。

【讨论】:

如果您要在现有标签的左侧添加第二个空白标签,您不妨覆盖sizeThatFits 或使用自动布局。

以上是关于向 UILabel 添加左/右水平填充的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Chart.js 条形图中添加左/右填充?

UILabel 使用 AutoLayout 实现具有居中放置和右侧按钮的 autoheight

iOS自动布局:将UILabel的左边缘与容器中的水平中心对齐?

左对齐的水平堆栈视图和顶部对齐的垂直堆栈视图

如何向引导程序版本 5 的容器流体类添加水平填充?

用内容复制 UILabel 并滑出一个右和一个左