我需要创建一个UILabel
具有背景颜色的,并且我想添加一些左/右前导/尾随水平填充。
但我发现的每一个解决方案似乎都是一个讨厌的黑客。
从 iOS 5 开始,实现这一目标的“标准”方式是什么?
一个截图来说明我的场景:
有关可用解决方案的完整列表,请参阅此答案: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)];
}
最重要的部分是您必须同时覆盖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))
}
在字符串中也添加一个空格字符。那是穷人的填充物:)
或者
我会使用自定义背景视图,但如果你不想要,空间是我看到的唯一其他简单的选项......
或编写自定义标签。通过 coretext 渲染文本
#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
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];
有时在原型制作时使用 UNICODE 部分空格来实现对齐很方便。这在原型设计、概念验证或只是推迟图形算法的实现时非常方便。
如果为方便起见使用 UNICODE 空格,请注意至少有一个 UNICODE 空格的大小取决于它所显示的字体,特别是实际的空格字符本身(U+0020,ASCII 32)
如果您在 UILabel 中使用默认的 iOS 系统字体,则默认系统字体特征可能会在随后的 iOS 版本中发生变化,并通过更改应用程序的精确间距突然引入不必要的错位。这可能而且确实会发生,例如“San Francisco”字体在 iOS 版本中替换了以前的 iOS 系统字体。
UNICODE 易于在 Swift 中指定,例如:
let six_per_em_space = "\u{2006}"
或者,将 HTML 页面中的空间直接剪切/粘贴到 Interface Builder 中的 UILabel 文本字段中。
注意:附图是截图,不是HTML,所以如果你想剪切/粘贴空间,请访问链接页面。
斯威夫特 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))
}
}
I had a couple of issues with the answers here, such as when you added in the padding, the width of the content was overflowing the box and that I wanted some corner radius. I solved this using the following subclass of 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
Hope that's helpful to someone! Note that if you wanted padding on the top and bottom, you would need to change this lines:
UIEdgeInsets insets = {0, PADDING, 0, PADDING};
To this:
UIEdgeInsets insets = {PADDING, PADDING, PADDING, PADDING};
And add this line underneath the similar one for width:
intrinsicSuperViewContentSize.height += PADDING * 2 ;
我为克服这个问题所做的一件事是使用 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。
这仍然是一种解决方法,但如果突出显示不打扰您,它会很好地工作。希望有用
子类 UILabel 并drawTextInRect:
像这样覆盖:
- (void)drawTextInRect:(CGRect)rect
{
UIEdgeInsets insets = {0, 10, 0, 0};
return [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
}
如果您需要比在文本左侧添加空格提供的更具体的文本对齐方式,您可以随时添加第二个空白标签,以准确说明您需要多少缩进。
我有文本左对齐的按钮,缩进为 10 像素,需要下面的标签才能对齐。它为标签提供了文本和左对齐,并将其放在 x=10 处,然后制作了一个具有相同背景颜色且宽度 = 10 的小第二个标签,并将其与真实标签对齐。
最少的代码,看起来不错。只是让 AutoLayout 让一切工作变得更加麻烦。