根据文本高度调整 UILabel 的高度

假设我在UILabel中有以下文本(一长行动态文本):

由于外星军队的数量远远超过了团队,玩家必须利用后世界末日的优势,比如在垃圾箱、柱子、汽车、瓦砾和其他物体后面寻找掩护。

我想要调整UILabel's的高度,以便文本可以容纳进去。我使用UILabel的以下属性使其中的文本自动换行。

myUILabel.lineBreakMode = UILineBreakModeWordWrap;
myUILabel.numberOfLines = 0;

如果我的排查方向不对,请告诉我。谢谢。

299249 次浏览

你可以用以下方式实现TableViewController's (UITableViewCell *)tableView:cellForRowAtIndexPath方法(例如):

#define CELL_LABEL_TAG 1


- (UITableViewCell *)tableView:(UITableView *)tableView  cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *text = @"my long text";


static NSString *MyIdentifier = @"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero  reuseIdentifier:identifier] autorelease];
}


CGFloat width = [UIScreen mainScreen].bounds.size.width - 50;
CGFloat height = [self textHeight:text] + 10;
CGRect frame = CGRectMake(10.0f, 10.0f, width, height);


UILabel *cellLabel = [[UILabel alloc] initWithFrame:frame];
cellLabel.tag = CELL_LABEL_TAG;
cellLabel.textColor = [UIColor blackColor];
cellLabel.backgroundColor = [UIColor clearColor];
cellLabel.textAlignment = UITextAlignmentLeft;
cellLabel.font = [UIFont systemFontOfSize:12.0f];
[cell.contentView addSubview:cellLabel];
[cellLabel release];


return cell;
}


UILabel *label = (UILabel *)[cell viewWithTag:CELL_LABEL_TAG];
label.text = text;
label.numberOfLines = 0;
[label sizeToFit];
return cell;

还可以使用NSStringsizeWithFont:constrainedToSize:lineBreakMode:方法来计算文本的高度。

sizeWithFont constrainedToSize:lineBreakMode:是要使用的方法。如何使用它的例子如下:

//Calculate the expected size based on the font and linebreak mode of your label
// FLT_MAX here simply means no constraint in height
CGSize maximumLabelSize = CGSizeMake(296, FLT_MAX);


CGSize expectedLabelSize = [yourString sizeWithFont:yourLabel.font constrainedToSize:maximumLabelSize lineBreakMode:yourLabel.lineBreakMode];


//adjust the label the the new height.
CGRect newFrame = yourLabel.frame;
newFrame.size.height = expectedLabelSize.height;
yourLabel.frame = newFrame;

最后,它成功了。谢谢大家。

我没有让它工作,因为我试图在heightForRowAtIndexPath方法中调整标签的大小:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

和(是的,我很傻),我在cellForRowAtIndexPath方法中调整标签的默认大小-我忽略了我之前写的代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

谢谢你写这篇文章。这对我帮助很大。在我的例子中,我也在一个单独的视图控制器中编辑文本。我注意到当我使用:

[cell.contentView addSubview:cellLabel];

在tableView:cellForRowAtIndexPath:方法中,每当我编辑单元格时,标签视图不断地在前一个视图之上呈现。文本变得像素化,当某些内容被删除或更改时,旧版本在新版本下可见。下面是我解决这个问题的方法:

if ([[cell.contentView subviews] count] > 0) {
UIView *test = [[cell.contentView subviews] objectAtIndex:0];
[test removeFromSuperview];
}
[cell.contentView insertSubview:cellLabel atIndex:0];

不再有奇怪的分层。如果有更好的处理方法,请告诉我。

一行是克里斯的答案是错的。

newFrame.size.height = maximumLabelSize.height;

应该是

newFrame.size.height = expectedLabelSize.height;

除此之外,这是正确的解决方案。

你的方向是对的。你所需要做的就是:

myUILabel.numberOfLines = 0;
myUILabel.text = @"Enter large amount of text here";
[myUILabel sizeToFit];

谢谢大家的帮助,这是我尝试的代码,这是为我工作

   UILabel *instructions = [[UILabel alloc]initWithFrame:CGRectMake(10, 225, 300, 180)];
NSString *text = @"First take clear picture and then try to zoom in to fit the ";
instructions.text = text;
instructions.textAlignment = UITextAlignmentCenter;
instructions.lineBreakMode = NSLineBreakByWordWrapping;
[instructions setTextColor:[UIColor grayColor]];


CGSize expectedLabelSize = [text sizeWithFont:instructions.font
constrainedToSize:instructions.frame.size
lineBreakMode:UILineBreakModeWordWrap];


CGRect newFrame = instructions.frame;
newFrame.size.height = expectedLabelSize.height;
instructions.frame = newFrame;
instructions.numberOfLines = 0;
[instructions sizeToFit];
[self addSubview:instructions];
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cellIdentifier = @"myCell";
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.myUILabel.lineBreakMode = UILineBreakModeWordWrap;
cell.myUILabel.numberOfLines = 0;
cell.myUILabel.text = @"Some very very very very long text....."
[cell.myUILabel.criterionDescriptionLabel sizeToFit];
}


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
CGFloat rowHeight = cell.myUILabel.frame.size.height + 10;


return rowHeight;
}

以下是分类版本:

< >强UILabel + AutoSize.h #进口< / p >

@interface UILabel (AutoSize)


- (void) autosizeForWidth: (int) width;


@end

UILabel + AutoSize.m

#import "UILabel+AutoSize.h"


@implementation UILabel (AutoSize)


- (void) autosizeForWidth: (int) width {
self.lineBreakMode = UILineBreakModeWordWrap;
self.numberOfLines = 0;
CGSize maximumLabelSize = CGSizeMake(width, FLT_MAX);
CGSize expectedLabelSize = [self.text sizeWithFont:self.font constrainedToSize:maximumLabelSize lineBreakMode:self.lineBreakMode];
CGRect newFrame = self.frame;
newFrame.size.height = expectedLabelSize.height;
self.frame = newFrame;
}


@end
UILabel *itemTitle = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, 10,100, 200.0f)];
itemTitle.text = @"aseruy56uiytitfesh";
itemTitle.adjustsFontSizeToFitWidth = NO;
itemTitle.autoresizingMask = UIViewAutoresizingFlexibleWidth;
itemTitle.font = [UIFont boldSystemFontOfSize:18.0];
itemTitle.textColor = [UIColor blackColor];
itemTitle.shadowColor = [UIColor whiteColor];
itemTitle.shadowOffset = CGSizeMake(0, 1);
itemTitle.backgroundColor = [UIColor blueColor];
itemTitle.lineBreakMode = UILineBreakModeWordWrap;
itemTitle.numberOfLines = 0;
[itemTitle sizeToFit];
[self.view addSubview:itemTitle];

使用这里所有的属性都使用在标签上,并通过增加itemTitle中的文本来测试它。文本

itemTitle.text = @"diofgorigjveghnhkvjteinughntivugenvitugnvkejrfgnvkhv";

它会根据你的需要给出完美的答案

当自动布局被启用时,调整大小不工作:)

在iOS 6中,Apple为UILabel添加了一个属性,极大地简化了标签的动态垂直大小调整:preferredMaxLayoutWidth

将此属性与lineBreakMode = nslinebreakbywordwrappedsizeToFit方法结合使用,可以轻松地将UILabel实例的大小调整为容纳整个文本的高度。

引用iOS文档:

preferredMaxLayoutWidth 多行标签的首选最大宽度(以点为单位)。 < br > < br > 讨论 当对标签应用布局约束时,此属性将影响标签的大小。在布局过程中,如果文本扩展到超出此属性指定的宽度,则附加文本将流动到一个或多个新行,从而增加标签的高度。

一个示例:

...
UILabel *status = [[UILabel alloc] init];
status.lineBreakMode = NSLineBreakByWordWrapping;
status.numberOfLines = 5; // limits to 5 lines; use 0 for unlimited.


[self addSubview:status]; // self here is the parent view


status.preferredMaxLayoutWidth = self.frame.size.width; // assumes the parent view has its frame already set.


status.text = @"Some quite lengthy message may go here…";
[status sizeToFit];
[status setNeedsDisplay];
...

根据iOS7更新

// If description are available for protocol
protocolDescriptionLabel.text = [dataDictionary objectForKey:@"description"];
[protocolDescriptionLabel sizeToFit];
[protocolDescriptionLabel setLineBreakMode:NSLineBreakByWordWrapping];


CGSize expectedLabelSize = [protocolDescriptionLabel
textRectForBounds:protocolDescriptionLabel.frame
limitedToNumberOfLines:protocolDescriptionLabel.numberOfLines].size;
NSLog(@"expectedLabelSize %f", expectedLabelSize.height);


//adjust the label the the new height.
CGRect newFrame = protocolDescriptionLabel.frame;
newFrame.size.height = expectedLabelSize.height;
protocolDescriptionLabel.frame = newFrame;

此方法适用于iOS 6和7

- (float)heightForLabelSize:(CGSize)maximumLabelSize  Font:(UIFont *)font String:(NSString*)string {


if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
NSDictionary *stringAttributes = [NSDictionary dictionaryWithObject:font forKey: NSFontAttributeName];


CGSize adjustedLabelSize = [string maximumLabelSize
options:NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesLineFragmentOrigin
attributes:stringAttributes context:nil].size;
return adjustedLabelSize.height;
}
else {
CGSize adjustedLabelSize = [string sizeWithFont:font constrainedToSize:maximumLabelSize lineBreakMode:NSLineBreakByWordWrapping];


return adjustedLabelSize.height;
}


}

你也可以把它作为一种方法。@Pyjamasam是非常正确的,所以我只是在创建它的方法。它可能对其他人有帮助

-(CGRect)setDynamicHeightForLabel:(UILabel*)_lbl andMaxWidth:(float)_width{
CGSize maximumLabelSize = CGSizeMake(_width, FLT_MAX);


CGSize expectedLabelSize = [_lbl.text sizeWithFont:_lbl.font constrainedToSize:maximumLabelSize lineBreakMode:_lbl.lineBreakMode];


//adjust the label the the new height.
CGRect newFrame = _lbl.frame;
newFrame.size.height = expectedLabelSize.height;
return newFrame;
}

就像这样

label.frame = [self setDynamicHeightForLabel:label andMaxWidth:300.0];

问题是,没有提到的函数是可靠的,一些字符串和字体将返回不正确的高度值。尤其是带属性的文本。

唯一可行的解决方案是:https://stackoverflow.com/a/4214978/699944,重点是使用CoreText手动计算每一行的高度,以获得正确的大小。没有其他已知的方法可以做到这一点。

iOS7之前和iOS7上面的解决方案

//
//  UILabel+DynamicHeight.m
//  For StackOverFlow
//
//  Created by Vijay on 24/02/14.
//  Copyright (c) 2014 http://Vijay-Apple-Dev.blogspot.com. All rights reserved.
//


#import <UIKit/UIKit.h>


#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)


#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)


#define iOS7_0 @"7.0"


@interface UILabel (DynamicHeight)


/*====================================================================*/


/* Calculate the size,bounds,frame of the Multi line Label */


/*====================================================================*/
/**
*  Returns the size of the Label
*
*  @param aLabel To be used to calculte the height
*
*  @return size of the Label
*/


-(CGSize)sizeOfMultiLineLabel;


@end




//
//  UILabel+DynamicHeight.m
//  For StackOverFlow
//
//  Created by Vijay on 24/02/14.
//  Copyright (c) 2014 http://Vijay-Apple-Dev.blogspot.com. All rights reserved.
//


#import "UILabel+DynamicHeight.h"


@implementation UILabel (DynamicHeight)
/*====================================================================*/


/* Calculate the size,bounds,frame of the Multi line Label */


/*====================================================================*/
/**
*  Returns the size of the Label
*
*  @param aLabel To be used to calculte the height
*
*  @return size of the Label
*/
-(CGSize)sizeOfMultiLineLabel{


NSAssert(self, @"UILabel was nil");


//Label text
NSString *aLabelTextString = [self text];


//Label font
UIFont *aLabelFont = [self font];


//Width of the Label
CGFloat aLabelSizeWidth = self.frame.size.width;




if (SYSTEM_VERSION_LESS_THAN(iOS7_0)) {
//version < 7.0


return [aLabelTextString sizeWithFont:aLabelFont
constrainedToSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT)
lineBreakMode:NSLineBreakByWordWrapping];
}
else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(iOS7_0)) {
//version >= 7.0


//Return the calculated size of the Label
return [aLabelTextString boundingRectWithSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{
NSFontAttributeName : aLabelFont
}
context:nil].size;


}


return [self bounds].size;


}


@end

对于那些迁移到iOS 8的人,这里有一个Swift的类扩展:

extension UILabel {


func autoresize() {
if let textNSString: NSString = self.text {
let rect = textNSString.boundingRectWithSize(CGSizeMake(self.frame.size.width, CGFloat.max),
options: NSStringDrawingOptions.UsesLineFragmentOrigin,
attributes: [NSFontAttributeName: self.font],
context: nil)
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, rect.height)
}
}


}

由于sizeWithFont已弃用,我使用这个代替。

这个得到标签特定属性。

-(CGFloat)heightForLabel:(UILabel *)label withText:(NSString *)text{


NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:@{NSFontAttributeName:label.font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){label.frame.size.width, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];


return ceil(rect.size.height);
}
NSString *str = @"Please enter your text......";
CGSize lblSize = [str sizeWithFont:[UIFont systemFontOfSize:15] constrainedToSize: CGSizeMake(200.0f, 600.0f) lineBreakMode: NSLineBreakByWordWrapping];


UILabel *label = [[UILabel alloc]init];
label.frame = CGRectMake(60, 20, 200, lblSize.height);
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
label.font = [UIFont systemFontOfSize:15];
label.text = str;
label.backgroundColor = [UIColor clearColor];
[label sizeToFit];
[self.view addSubview:label];

我的代码:

UILabel *label      = [[UILabel alloc] init];
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
label.text          = text;
label.textAlignment = NSTextAlignmentCenter;
label.font          = [UIFont fontWithName:_bodyTextFontFamily size:_bodyFontSize];


CGSize size = [label sizeThatFits:CGSizeMake(width, MAXFLOAT)];




float height        = size.height;
label.frame         = CGRectMake(x, y, width, height);

您可以在设计时在Storyboard/XIB中这样做,而不是通过编程来完成。

  • 在属性检查器中将UIlabel的行数属性设置为0
  • 然后根据需要设置宽度约束/(或)前导和后导约束。
  • 然后用最小值 设置高度约束。最后选择你添加的高度约束,在大小检查器属性检查器旁边,改变高度约束的关系等于 - 大于

更新方法

+ (CGFloat)heightForText:(NSString*)text font:(UIFont*)font withinWidth:(CGFloat)width {


CGSize constraint = CGSizeMake(width, 20000.0f);
CGSize size;


CGSize boundingBox = [text boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:font}
context:nil].size;


size = CGSizeMake(ceil(boundingBox.width), ceil(boundingBox.height));


return size.height;
}

斯威夫特2:

    yourLabel.text = "your very long text"
yourLabel.numberOfLines = 0
yourLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
yourLabel.frame.size.width = 200
yourLabel.frame.size.height = CGFloat(MAXFLOAT)
yourLabel.sizeToFit()

有趣的行是sizeToFit(),并将frame.size.height设置为最大浮点数,这将为长文本提供空间,但sizeToFit()将强制它只使用必要的,但总是在设置.frame.size.height后调用它。

我建议为调试目的设置.backgroundColor,这样你就可以看到每个情况下呈现的帧。

这种方法可以得到完美的高度

-(float) getHeightForText:(NSString*) text withFont:(UIFont*) font andWidth:(float) width{
CGSize constraint = CGSizeMake(width , 20000.0f);
CGSize title_size;
float totalHeight;




title_size = [text boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{ NSFontAttributeName : font }
context:nil].size;


totalHeight = ceil(title_size.height);


CGFloat height = MAX(totalHeight, 40.0f);
return height;
}

检查这个工作完美,没有添加单行代码。使用自动布局()

我根据你的要求做了一个演示给你。从下面的链接下载,

自动调整UIView和UILabel的大小

循序渐进指南:-

第一步:-将constraint设置为UIView

1)领先2)领先3)落后(主视图)

enter image description here

第二步:将constraint设置为Label 1

1)领先2)顶部3)尾随(从它的父视图)

enter image description here

第三步:-将constraint设置为Label 2

1)领先2)尾随(从它的父视图)

enter image description here

第四步:- 最棘手的给按钮从UIView的UILabel。

enter image description here

第五步:(可选)将constraint设置为UIButton

1)领先2)底部3)后拖4)固定高度(从主视图开始)

enter image description here

输出:

enter image description here

注意:-确保你在Label属性中设置了Number of lines =0。

enter image description here

我希望这个信息足以理解Autoresize UIView根据UILabel的高度和Autoresize UILabel根据文本。

对我来说,最简单和更好的方法是应用高度约束标签和设置优先级低,即(250)在故事板。

所以你不需要担心通过编程计算高度和宽度,多亏了storyboard。

myLabel.text = "your very long text"
myLabel.numberOfLines = 0
myLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping

请在故事板中为可用性设置约束,包括左上右下

要在Swift3中做到这一点,以下是代码:

 let labelSizeWithFixedWith = CGSize(width: 300, height: CGFloat.greatestFiniteMagnitude)
let exactLabelsize = self.label.sizeThatFits(labelSizeWithFixedWith)
self.label.frame = CGRect(origin: CGPoint(x: 20, y: 20), size: exactLabelsize)

这是使用Objective-c获取UILabel Height的一行代码:

labelObj.numberOfLines = 0;
CGSize neededSize = [labelObj sizeThatFits:CGSizeMake(screenWidth, CGFLOAT_MAX)];

使用.height你会得到标签的高度,如下所示:

neededSize.height

我计算UILabel动态高度的方法。

    let width = ... //< width of this label
let text = ... //< display content


label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.preferredMaxLayoutWidth = width


// Font of this label.
//label.font = UIFont.systemFont(ofSize: 17.0)
// Compute intrinsicContentSize based on font, and preferredMaxLayoutWidth
label.invalidateIntrinsicContentSize()
// Destination height
let height = label.intrinsicContentSize.height

包装功能:

func computeHeight(text: String, width: CGFloat) -> CGFloat {
// A dummy label in order to compute dynamic height.
let label = UILabel()


label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.font = UIFont.systemFont(ofSize: 17.0)


label.preferredMaxLayoutWidth = width
label.text = text
label.invalidateIntrinsicContentSize()


let height = label.intrinsicContentSize.height
return height
}

再加上上述答案:

这可以通过故事板轻松实现。

  1. 为UILabel设置约束。(在我的情况下,我做了顶部,左边和固定宽度)
  2. 在属性检查器中设置到0的行数
  3. 在属性检查器中设置换行到WordWrap

UILabel Height Adjust

UILabel扩展基于这个答案Swift 4及以上

extension UILabel {


func retrieveTextHeight () -> CGFloat {
let attributedText = NSAttributedString(string: self.text!, attributes: [NSFontAttributeName:self.font])


let rect = attributedText.boundingRect(with: CGSize(width: self.frame.size.width, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, context: nil)


return ceil(rect.size.height)
}


}

可以这样使用:

self.labelHeightConstraint.constant = self.label.retrieveTextHeight()

你可以使用下面的代码得到高度

你必须通过

  1. < p >文本2。字体3。标签宽度

    func heightForLabel(text: String, font: UIFont, width: CGFloat) -> CGFloat {
    
    
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text
    label.sizeToFit()
    
    
    return label.frame.height
    }