cocoa-touch - UILabel 垂直对齐文本框

  显示原文与译文双语对照的内容

我有一个带两行文本的UILabel 。 有时,当文本太短时,此文本显示在标签的垂直中心。

如何垂直对齐文本,使它的始终位于 UILabel的顶部?

enter image description here

时间:

无法在 UILabel 上设置垂直对齐方式,但通过更改标签的框架可以获得相同的效果。 我把我的标签做成橙色,这样你可以清楚地看到发生了什么。

下面是快速和简单的方法:


 [myLabel sizeToFit];

sizeToFit to squeeze a label


如果有一个标签较长的标签,该标签会使多行上,请将 numberOfLines 设置为 0 ( 零表示无限的行数) 。


 myLabel.numberOfLines = 0;
 [myLabel sizeToFit];

Longer label text with sizeToFit


的版本

我将把我的标签放在代码中,这样你就可以看到发生了什么。 你可以在接口生成器中设置大部分内容。 我的设置是一个基于视图的应用,我在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的一些限制在center-或者right-aligned文本中发挥作用。 以下是发生的情况:


//myLabel.textAlignment = NSTextAlignmentRight;
 myLabel.textAlignment = NSTextAlignmentCenter;

 [myLabel setNumberOfLines:0];
 [myLabel sizeToFit];

enter image description here

标签仍然使用固定的top-left角点调整大小。 你可以在变量中保存标签的原始宽度,并将它的设置为 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;

label alignment


注意 sizeToFit 将尊重你最初的最小标签宽度。 如果你上来就用 100标签 sizeToFit 100宽可以调用就可以了,它会给你返回一个( 可能很高) 标签( 或者稍微少一点) 宽度。 调整大小之前,你可能希望将标签设置为所需的最小宽度。

Correct label alignment by resizing the frame width

需要注意的其他事项:

是否尊重 lineBreakMode 取决于它的设置方式。 NSLineBreakByTruncatingTail ( 默认值) 在 sizeToFit 之后被忽略,另外两个截断模式( 头部和中部) 。 NSLineBreakByClipping 也被忽略。NSLineBreakByCharWrapping 正常工作。 框架宽度仍然缩小到最右边的字母。


标记 Amery 为NIBs和 Storyboard 在注释中使用自动布局提供了一个修复:

如果你的标签是包含在一个笔尖或者 Storyboard 作为subview的view 一个 ViewController,用的是自动布局,你接着在上述 sizeToFit 调入 viewDidLoad subviews viewDidLoad 被调用后并不可行,因为自动布局大小和位置将立即消除-的效果你 sizeToFit 电话。 在 viewDidLayoutSubviews 内将 work,但是,调用


我原来回答( 对于后代/参考):

使用 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;

这里页面具有相同解决方案的一些不同代码:

中的讨论

1 ) 设置新文本:

myLabel.text = @"Some Text"

2 ) 将行的maximum number 设置为 0 ( 自动):

myLabel.numberOfLines = 0

3 ) 将标签的框架设置为最大大小:

myLabel.frame = CGRectMake(20,20,200,800)

4 ) 调用 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"];

在每个添加的换行符中需要额外的空间,因为 UILabels'尾部的回车似乎被忽略:(

类似地,alignBottom也应该更新,使用 @" n@%" 代替 "n@%" ( 循环初始化必须替换为"进行( 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

然后每个 assignment, yourLabel文本后调用 [yourLabel alignTop]; 或者

就像上面的答案,但它不是很正确,或者很容易进入代码,所以我把它清理干净一点。 将这里扩展添加到它自己的. 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];

更快的( 和 dirtier ) 方法是将uilabel中断模式的行设置为"剪辑"并添加一个固定的换行符。


myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"nnnn"];

这个解决方案对于每个--都不起作用,如果你仍然想在字符串末尾显示"。。",那么你需要使用一个较长的代码 Fragment,这将会让你得到需要的代码。

在使用 UILabel 而不愿使用以防万一它是任何帮助给所有人,我有同样的问题,但能够解决所面对的问题简单地通过 switching. 我欣赏这不是针对所有人,因为功能有点不同。

如果要使用 switch 来使用 UITextView,可以关闭所有滚动视图属性以及启用用户交互。。 这将迫使它更像一个标签。

而不是 UILabel,你可以使用具有垂直对齐选项的UITextField:


textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO;//Don't allow interaction

我已经很长时间了,我想分享我的解决方案。

这将给你一个 UILabel,它将autoshrink文本缩小到 0.5个刻度并垂直居中文本。 这些选项在 Storyboard/ib中也可用。


[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];

enter image description here

在接口生成器中

  • UILabel 设置为最大可能文本的大小
  • 在属性检查器中将 Lines 设置为'0'

在你的代码中

  • 设置标签的文本
  • 在你的标签上调用 sizeToFit

代码段:


self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];

创建新类

LabelTopAlign

h 文件


#import <UIKit/UIKit.h>


@interface KwLabelTopAlign : UILabel {

}

@end

m 文件


#import"KwLabelTopAlign.h"


@implementation KwLabelTopAlign

- (void)drawTextInRect:(CGRect)rect {
 int lineHeight = [@"IglL" sizeWithFont:self.font constrainedToSize:CGSizeMake(rect.size.width, 9999.0f)].height;
 if(rect.size.height> = lineHeight) {
 int textHeight = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(rect.size.width, rect.size.height)].height;
 int yMax = textHeight;
 if (self.numberOfLines> 0) {
 yMax = MIN(lineHeight*self.numberOfLines, yMax); 
 }

 [super drawTextInRect:CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, yMax)];
 }
}

@end

编辑

下面是一个实现相同的简单实现:


#import"KwLabelTopAlign.h"

@implementation KwLabelTopAlign

- (void)drawTextInRect:(CGRect)rect
{
 CGFloat height = [self.text sizeWithFont:self.font
 constrainedToSize:rect.size
 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];
}

@end

...