UILabel 的 sizeToFit/sizeThatFits 忽略 numberoflines 属性

Posted

技术标签:

【中文标题】UILabel 的 sizeToFit/sizeThatFits 忽略 numberoflines 属性【英文标题】:UILabel's sizeToFit/sizeThatFits ignore the numberoflines property 【发布时间】:2011-02-18 13:30:46 【问题描述】:

问题:确定UILabel 需要的大小(行数),假设宽度为 300 像素。字符串较长,所以我将lineBreakMode 设置为UILineBreakModeWordWrap 并调用sizeThatFits 来尝试确定大小。但它在单行中给出了 457 像素的宽度,而不是预期的两行中的 300 像素。

请看:

CGSize available = CGSizeMake(300, INFINITY);
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 300, 400)] autorelease];
label.text = title;
label.lineBreakMode = UILineBreakModeWordWrap;
label.font = [UIFont fontWithName:kBoldFont size:kTitleFontSize];
label.numberOfLines = 3;
CGSize sizedtoFit = [label sizeThatFits:available];

但我发现 sizedtoFit 变量的宽度为 457 像素,高度为 22 像素,并且 UI 显示单行并带有剪切的文本。我预计两条线的宽度为 300 像素,高度为 44 像素。

numberoflines 的 UILabel 文档说:

当使用sizeToFit 方法调整接收器的大小时,调整大小会考虑存储在此属性中的值。例如,如果此属性设置为 3,sizeToFit 方法会调整接收器的大小,使其大到足以显示三行文本。

我尝试了以下各种组合:

    CGRectZero 传递给 init 函数,传递 300x400 或 300 x 无穷大。 在创建后设置框架,而不是将其传递给 init 函数。 调用 [sizeToFit] 并希望它在假设当前宽度的情况下计算高度,但事实并非如此。 调用 sizeToFit,然后调用 sizeThatFits`。 调用layoutIfNeeded

它们都不起作用。我做错了什么,或者这是文档和框架实现不一致的错误?谢谢。

【问题讨论】:

根据文档,我认为这是一个错误,我刚刚报告了它。 这似乎在 ios6 中已修复 - [ sizeToFit] 现在将 numberOfLines 考虑在内。 @Pavel 是对的,刚刚从 5.1 升级到 6.0 并且神奇地 sizeToFit 返回了正确的大小(增加了高度)。 【参考方案1】:

我遇到了同样的问题,适合的尺寸只是忽略了尺寸... /: 我最终使用了:

CGRect textSize = [UILabel textRectForBounds:CGRectMake(0, 0, 300, CGFLOAT_MAX) 
                      limitedToNumberOfLines:3];

像魅力一样工作...... :)

文档说你不应该直接调用它,但我已经使用它一段时间了,有批准的提交应用程序,一切都很棒...... :)

【讨论】:

除非万不得已,否则我不会这样做 :) 想详细说明@KartickVaddadi 吗? :) 好吧,我不想做文档上说不应该做的事情,除非万不得已。 这是否假定您使用的是默认字体? 使用实例方法CGRect textSize = [label textRectForBounds:CGRectMake(0, 0, 300, CGFLOAT_MAX) limitedToNumberOfLines:3] 的当前文档似乎很好。注意:这不是@AlexZak 回答中的类方法。参考:developer.apple.com/library/ios/documentation/uikit/reference/…:【参考方案2】:

你试过sizeWithFont: constrainedToSize: lineBreakMode:方法吗?

例如:

CGSize sizeToFit = [title sizeWithFont:label.font constrainedToSize:label.frame.size lineBreakMode:label.lineBreakMode];

【讨论】:

那是我的后备选项,但问题是:为什么 sizeThatFits 不能正常工作?刚刚有人告诉我,如果我将 numberOfLines 设置为 0(无限制),它会起作用。 如果您想要最多三行,就像暗示的问题一样,这并不好。猜猜我需要计算三行的高度,然后将其传递给 sizeWithFont 函数。这很糟糕。 很好的答案。我发现这对多行标签最有用。不过,在 iOS7 中不推荐使用 sizeWithFont。使用 boundingRectWithSize 查看我的单独答案:【参考方案3】:

我发现 Ian L 的答案最好使用 -sizeWithFont:constrainedToSize:lineBreakMode:,不幸的是 sizeWithFont: 在 iOS7 下已弃用。

这就是 sizeWithFont: 在 iOS7 中为 UILabel 子类工作的方式:

NSRange range = NSMakeRange(0, self.attributedText.length); 
sizeToFit = [self.text boundingRectWithSize:self.bounds.size
                                    options:NSStringDrawingUsesLineFragmentOrigin 
                                 attributes:[self.attributedText 
                          attributesAtIndex:0 effectiveRange:&range] context:nil].size;

【讨论】:

【参考方案4】:

我认为你得到了意想不到的结果,因为你没有考虑到UILabel 的字体。请尝试以下操作:

UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 300, 400)] autorelease];
label.text = title;
label.lineBreakMode = UILineBreakModeWordWrap;
label.font = [UIFont fontWithName:kBoldFont size:kTitleFontSize];
label.numberOfLines = 0;

CGSize size = [label.text sizeWithFont:label.font constrainedToSize:CGSizeMake(label.frame.size.width,FLT_MAX) lineBreakMode:UILineBreakModeWordWrap ];
label.frame = CGRectMake(label.frame.origin.x,label.frame.origin.y,label.frame.size.width,size.height);

【讨论】:

此方案不限制行数 除了不限制行数之外,它还使用了NSString的大小调整方法,这将忽略UILabel的大量附加功能【参考方案5】:

sizeToFit 的 ios5 没有解决方案。您可以使用其他解决方案,如sizeWithFont 等。在 ios6 中,该问题已修复。但是,我的解决方案有以下解决方法:

int lineCount = myLabel.numberOfLines;
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
myLabel.numberOfLines = lineCount;

而且它有效。请注意,对于我的情况,标签的宽度是固定的,我只需要 sizeToFit 来调整高度。

【讨论】:

【参考方案6】:

这一切都已弃用。使用 boundingRectWithSize

【讨论】:

以上是关于UILabel 的 sizeToFit/sizeThatFits 忽略 numberoflines 属性的主要内容,如果未能解决你的问题,请参考以下文章

如何调整 UIView 的大小以获取大量 UILabel 并调整 UILabel 的大小以适合文本?

UILabel

UIAlertController 或 UITextField 中的 UILabel 类似 UILabel

IOS开发调整UILabel的行间距

如何仅使用情节提要使 UILabel 的 UIView 超级视图适合 UILabel 的固有高度?

ios6--UILabel