我有一个 UILabel
有两行文字的空间。有时,当文本太短时,此文本显示在标签的垂直中心。
如何垂直对齐文本始终位于顶部 UILabel
?
我有一个 UILabel
有两行文字的空间。有时,当文本太短时,此文本显示在标签的垂直中心。
如何垂直对齐文本始终位于顶部 UILabel
?
没有办法在a上设置垂直对齐 UILabel
,但你可以通过改变标签的框架来获得相同的效果。我把标签变成橙色,这样你就可以清楚地看到发生了什么。
这是快速简便的方法:
[myLabel sizeToFit];
如果您的文本较长的标签将生成多行,请进行设置 numberOfLines
至 0
(零表示无限数量的行)。
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
版本更长
我将在代码中制作我的标签,以便您可以看到正在发生的事情。您也可以在Interface Builder中设置大部分内容。我的设置是一个基于视图的应用程序,带有我在Photoshop中制作的背景图像,以显示边距(20分)。标签是一种诱人的橙色,因此您可以看到尺寸发生了什么。
- (void)viewDidLoad
{
[super viewDidLoad];
// 20 point top and left margin. Sized to leave 20 pt at right.
CGRect labelFrame = CGRectMake(20, 20, 280, 150);
UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
[myLabel setBackgroundColor:[UIColor orangeColor]];
NSString *labelText = @"I am the very model of a modern Major-General, I've information vegetable, animal, and mineral";
[myLabel setText:labelText];
// Tell the label to use an unlimited number of lines
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
[self.view addSubview:myLabel];
}
使用的一些限制 sizeToFit
发挥中心或右对齐文本。这是发生的事情:
// myLabel.textAlignment = NSTextAlignmentRight;
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
标签的大小仍然是固定的左上角。您可以将原始标签的宽度保存在变量中并在之后进行设置 sizeToFit
,或给它一个固定的宽度来解决这些问题:
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
CGRect myFrame = myLabel.frame;
// Resize the frame's width to 280 (320 - margins)
// width could also be myOriginalLabelFrame.size.width
myFrame = CGRectMake(myFrame.origin.x, myFrame.origin.y, 280, myFrame.size.height);
myLabel.frame = myFrame;
注意 sizeToFit
将尊重您的初始标签的最小宽度。如果您从100宽的标签开始并致电 sizeToFit
在它上面,它会给你一个(可能很高)标签,宽度为100(或更小)。您可能希望在调整大小之前将标签设置为所需的最小宽度。
其他一些注意事项:
是否 lineBreakMode
受到尊重取决于它是如何设置的。 NSLineBreakByTruncatingTail
(默认值)后会被忽略 sizeToFit
,以及其他两种截断模式(头部和中部)。 NSLineBreakByClipping
也被忽略了。 NSLineBreakByCharWrapping
像往常一样工作。框架宽度仍然缩小以适合最右边的字母。
马克·阿梅里 在评论中使用自动布局修复了NIB和故事板:
如果您的标签作为子视图包含在笔尖或故事板中
view
一个使用autolayout的ViewController,然后把你的sizeToFit
打电话给viewDidLoad
将无法正常工作,因为autolayout大小和位置后的子视图viewDidLoad
被调用并将立即撤消你的影响sizeToFit
呼叫。但是,打电话sizeToFit
从内部viewDidLayoutSubviews
将 工作。
这使用了 NSString
方法 sizeWithFont:constrainedToSize:lineBreakMode:
计算拟合字符串所需的帧高度,然后设置原点和宽度。
使用要插入的文本调整标签的框架大小。这样你可以容纳任意数量的线。
CGSize maximumSize = CGSizeMake(300, 9999);
NSString *dateString = @"The date today is January 1st, 1999";
UIFont *dateFont = [UIFont fontWithName:@"Helvetica" size:14];
CGSize dateStringSize = [dateString sizeWithFont:dateFont
constrainedToSize:maximumSize
lineBreakMode:self.dateLabel.lineBreakMode];
CGRect dateFrame = CGRectMake(10, 10, 300, dateStringSize.height);
self.dateLabel.frame = dateFrame;
没有办法在a上设置垂直对齐 UILabel
,但你可以通过改变标签的框架来获得相同的效果。我把标签变成橙色,这样你就可以清楚地看到发生了什么。
这是快速简便的方法:
[myLabel sizeToFit];
如果您的文本较长的标签将生成多行,请进行设置 numberOfLines
至 0
(零表示无限数量的行)。
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
版本更长
我将在代码中制作我的标签,以便您可以看到正在发生的事情。您也可以在Interface Builder中设置大部分内容。我的设置是一个基于视图的应用程序,带有我在Photoshop中制作的背景图像,以显示边距(20分)。标签是一种诱人的橙色,因此您可以看到尺寸发生了什么。
- (void)viewDidLoad
{
[super viewDidLoad];
// 20 point top and left margin. Sized to leave 20 pt at right.
CGRect labelFrame = CGRectMake(20, 20, 280, 150);
UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
[myLabel setBackgroundColor:[UIColor orangeColor]];
NSString *labelText = @"I am the very model of a modern Major-General, I've information vegetable, animal, and mineral";
[myLabel setText:labelText];
// Tell the label to use an unlimited number of lines
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
[self.view addSubview:myLabel];
}
使用的一些限制 sizeToFit
发挥中心或右对齐文本。这是发生的事情:
// myLabel.textAlignment = NSTextAlignmentRight;
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
标签的大小仍然是固定的左上角。您可以将原始标签的宽度保存在变量中并在之后进行设置 sizeToFit
,或给它一个固定的宽度来解决这些问题:
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
CGRect myFrame = myLabel.frame;
// Resize the frame's width to 280 (320 - margins)
// width could also be myOriginalLabelFrame.size.width
myFrame = CGRectMake(myFrame.origin.x, myFrame.origin.y, 280, myFrame.size.height);
myLabel.frame = myFrame;
注意 sizeToFit
将尊重您的初始标签的最小宽度。如果您从100宽的标签开始并致电 sizeToFit
在它上面,它会给你一个(可能很高)标签,宽度为100(或更小)。您可能希望在调整大小之前将标签设置为所需的最小宽度。
其他一些注意事项:
是否 lineBreakMode
受到尊重取决于它是如何设置的。 NSLineBreakByTruncatingTail
(默认值)后会被忽略 sizeToFit
,以及其他两种截断模式(头部和中部)。 NSLineBreakByClipping
也被忽略了。 NSLineBreakByCharWrapping
像往常一样工作。框架宽度仍然缩小以适合最右边的字母。
马克·阿梅里 在评论中使用自动布局修复了NIB和故事板:
如果您的标签作为子视图包含在笔尖或故事板中
view
一个使用autolayout的ViewController,然后把你的sizeToFit
打电话给viewDidLoad
将无法正常工作,因为autolayout大小和位置后的子视图viewDidLoad
被调用并将立即撤消你的影响sizeToFit
呼叫。但是,打电话sizeToFit
从内部viewDidLayoutSubviews
将 工作。
这使用了 NSString
方法 sizeWithFont:constrainedToSize:lineBreakMode:
计算拟合字符串所需的帧高度,然后设置原点和宽度。
使用要插入的文本调整标签的框架大小。这样你可以容纳任意数量的线。
CGSize maximumSize = CGSizeMake(300, 9999);
NSString *dateString = @"The date today is January 1st, 1999";
UIFont *dateFont = [UIFont fontWithName:@"Helvetica" size:14];
CGSize dateStringSize = [dateString sizeWithFont:dateFont
constrainedToSize:maximumSize
lineBreakMode:self.dateLabel.lineBreakMode];
CGRect dateFrame = CGRectMake(10, 10, 300, dateStringSize.height);
self.dateLabel.frame = dateFrame;
设置新文本:
myLabel.text = @"Some Text"
设置 maximum number
行为0(自动):
myLabel.numberOfLines = 0
将标签的框架设置为最大尺寸:
myLabel.frame = CGRectMake(20,20,200,800)
呼叫 sizeToFit
减少框架大小,使内容适合:
[myLabel sizeToFit]
现在,标签框架的高度和宽度足以适合您的文字。左上角应保持不变。我只用左上对齐的文本测试了这个。对于其他对齐,您可能必须在之后修改框架。
此外,我的标签启用了自动换行。
参考扩展解决方案:
for(int i=1; i< newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n"];
应该被替换
for(int i=0; i<newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n "];
每个添加的换行符都需要额外的空间,因为iPhone UILabels
'尾随回车似乎被忽略了:(
同样,alignBottom也应该用a更新 @" \n@%"
代替 "\n@%"
(循环初始化必须替换为“for(int i = 0 ...”)。
以下扩展适用于我:
// -- file: UILabel+VerticalAlign.h
#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end
// -- file: UILabel+VerticalAlign.m
@implementation UILabel (VerticalAlign)
- (void)alignTop {
CGSize fontSize = [self.text sizeWithFont:self.font];
double finalHeight = fontSize.height * self.numberOfLines;
double finalWidth = self.frame.size.width; //expected width of label
CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i=0; i<newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n "];
}
- (void)alignBottom {
CGSize fontSize = [self.text sizeWithFont:self.font];
double finalHeight = fontSize.height * self.numberOfLines;
double finalWidth = self.frame.size.width; //expected width of label
CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i=0; i<newLinesToPad; i++)
self.text = [NSString stringWithFormat:@" \n%@",self.text];
}
@end
然后打电话 [yourLabel alignTop];
要么 [yourLabel alignBottom];
在每个yourLabel文本分配之后。
为了防止对任何人有任何帮助,我遇到了同样的问题,但只需从使用切换就能解决问题 UILabel
使用 UITextView
。我很欣赏这并不适合所有人,因为功能有点不同。
如果你切换到使用 UITextView
,您可以关闭所有滚动视图属性以及启用用户交互...这将强制它更像标签。
没有麻烦,没有大惊小怪
@interface MFTopAlignedLabel : UILabel
@end
@implementation MFTopAlignedLabel
- (void)drawTextInRect:(CGRect) rect
{
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:self.text attributes:@{NSFontAttributeName:self.font}];
rect.size.height = [attributedText boundingRectWithSize:rect.size
options:NSStringDrawingUsesLineFragmentOrigin
context:nil].size.height;
if (self.numberOfLines != 0) {
rect.size.height = MIN(rect.size.height, self.numberOfLines * self.font.lineHeight);
}
[super drawTextInRect:rect];
}
@end
没有muss,没有Objective-c,没有大惊小怪但是Swift 3:
class VerticalTopAlignLabel: UILabel {
override func drawText(in rect:CGRect) {
guard let labelText = text else { return super.drawText(in: rect) }
let attributedText = NSAttributedString(string: labelText, attributes: [NSFontAttributeName: font])
var newRect = rect
newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height
if numberOfLines != 0 {
newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
}
super.drawText(in: newRect)
}
}
就像上面的答案,但它不是很正确,或者很容易打入代码,所以我清理了一下。将此扩展名添加到它自己的.h和.m文件中,或者只是粘贴到您打算使用它的实现上方:
#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end
@implementation UILabel (VerticalAlign)
- (void)alignTop
{
CGSize fontSize = [self.text sizeWithFont:self.font];
double finalHeight = fontSize.height * self.numberOfLines;
double finalWidth = self.frame.size.width; //expected width of label
CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i=0; i<= newLinesToPad; i++)
{
self.text = [self.text stringByAppendingString:@" \n"];
}
}
- (void)alignBottom
{
CGSize fontSize = [self.text sizeWithFont:self.font];
double finalHeight = fontSize.height * self.numberOfLines;
double finalWidth = self.frame.size.width; //expected width of label
CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i=0; i< newLinesToPad; i++)
{
self.text = [NSString stringWithFormat:@" \n%@",self.text];
}
}
@end
然后使用,将您的文本放入标签,然后调用适当的方法来对齐它:
[myLabel alignTop];
要么
[myLabel alignBottom];
更快(更脏)的方法是将UILabel的换行模式设置为“Clip”并添加固定数量的换行符。
myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];
此解决方案不适用于所有人 - 特别是,如果您仍希望在字符串末尾显示“...”,如果它超出您显示的行数,则需要使用其中一个更长的代码 - 但在很多情况下,这将为您提供所需的。