我有一个UILabel,它有两行文字的空间。有时,当文本太短时,此文本会显示在标签的垂直中心。
如何垂直对齐文本,使其始终位于UILabel的顶部?
我有一个UILabel,它有两行文字的空间。有时,当文本太短时,此文本会显示在标签的垂直中心。
如何垂直对齐文本,使其始终位于UILabel的顶部?
当前回答
此代码帮助您使文本与顶部对齐,并使标签高度与文本内容固定。
使用以下代码的说明
默认情况下,isHeightToChange会自动将标签的高度设置为与文本内容相同。isHeightToChange如果为false,则使文本对齐到顶部,而不降低标签的高度。
#import "DynamicHeightLable.h"
@implementation DynamicHeightLable
@synthesize isHeightToChange;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// Initialization code.
self.isHeightToChange=FALSE;//default
}
return self;
}
- (void)drawTextInRect:(CGRect)rect
{
if(!isHeightToChange){
CGSize maximumLabelSize = CGSizeMake(self.frame.size.width,2500);
CGFloat height = [self.text sizeWithFont:self.font
constrainedToSize:maximumLabelSize
lineBreakMode:self.lineBreakMode].height;
if (self.numberOfLines != 0) {
height = MIN(height, self.font.lineHeight * self.numberOfLines);
}
rect.size.height = MIN(rect.size.height, height);
}
[super drawTextInRect:rect];
}
- (void) layoutSubviews
{
[super layoutSubviews];
if(isHeightToChange){
CGRect ltempFrame = self.frame;
CGSize maximumLabelSize = CGSizeMake(self.frame.size.width,2500);
CGFloat height = [self.text sizeWithFont:self.font
constrainedToSize:maximumLabelSize
lineBreakMode:self.lineBreakMode].height;
if (self.numberOfLines != 0) {
height = MIN(height, self.font.lineHeight * self.numberOfLines);
}
ltempFrame.size.height = MIN(ltempFrame.size.height, height);
ltempFrame.size.height=ltempFrame.size.height;
self.frame=ltempFrame;
}
}
@end
其他回答
如果您使用的是自动布局,请在代码或IB中将垂直内容HuggingPriority设置为1000。在IB中,您可能需要通过将其优先级设置为1然后删除来删除高度限制。
无法在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照常工作。框架宽度仍然变窄,以适合最右边的字母。
Mark Amery在评论中使用Auto Layout修复了NIB和Storyboards:
如果标签包含在笔尖或情节提要中,作为使用自动布局的ViewController视图的子视图,那么将sizeToFit调用放入viewDidLoad将不起作用,因为在调用viewDidLoad后自动布局将调整子视图的大小和位置,并将立即撤消sizeToFit调用的效果。但是,从viewDidLayoutSubviews内调用sizeToFit将起作用。
我的原始答案(供后人参考):
这使用NSString方法sizeWithFont:consainedToSize: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;
我花了一段时间阅读了代码,以及介绍页面中的代码,发现它们都试图修改标签的框架大小,这样就不会出现默认的中心垂直对齐。
然而,在某些情况下,我们确实希望标签占据所有这些空间,即使标签确实有太多文本(例如,高度相等的多行)。
在这里,我使用了另一种方法来解决这个问题,只需在标签末尾添加换行符(请注意,我实际上继承了UILabel,但这不是必须的):
CGSize fontSize = [self.text sizeWithFont:self.font];
finalHeight = fontSize.height * self.numberOfLines;
finalWidth = 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 "];
}
您可以使用TTTAttributedLabel,它支持垂直对齐。
@property (nonatomic) TTTAttributedLabel* label;
<...>
//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
在UILabel中,无法垂直对齐文本。但是,您可以使用NSString的sizeWithFont:方法动态更改标签的高度,并根据需要设置其x和y。
您可以使用UITextField。它支持contentVerticalAlignment人员,因为它是UIControl的子类。您必须将其userInteractionEnabled设置为NO,以防止用户在其上键入文本。