objective-c iPhone UILabel sizeWithFont:

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1204000/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:59:31  来源:igfitidea点击:

iPhone UILabel sizeWithFont:

iphoneobjective-cfontsuilabel

提问by CVertex

I'm trying to measure the visual size of a NSString that takes into account the number of lines I can render. However, sizeWithFont doesn't take into account numberOfLines property? So my layout algorithm positions everything lower than they actually need to be.

我正在尝试测量考虑到我可以渲染的行数的 NSString 的视觉大小。但是, sizeWithFont 没有考虑 numberOfLines 属性?所以我的布局算法把所有东西都放在比它们实际需要的位置低的位置。

_price = [[UILabel alloc] init];
_price.text = myPriceValue;
_price.lineBreakMode = UILineBreakModeWordWrap;
_price.numberOfLines = 3;
_price.backgroundColor = [UIColor clearColor];
_price.textColor = TTSTYLEVAR(colorPrice);
/// the follow code ignores numberOfLines and just tells me the size of the whole block.  
// I'd like it to be aware of numberOfLines
//
CGSize priceSize = [_price.text sizeWithFont:_price.font
        constrainedToSize:CGSizeMake(maxWidth, CGFLOAT_MAX)
        lineBreakMode:UILineBreakModeWordWrap];

Does anyone know how to do this using the iPhone SDK?

有谁知道如何使用 iPhone SDK 做到这一点?

回答by Kevlar

Instead of CGFLOAT_MAX for the max height of your text calculation, try getting the size of one line with this:

而不是 CGFLOAT_MAX 用于文本计算的最大高度,请尝试使用以下方法获取一行的大小:

[_price.text sizeWithFont:_price.font].height

and then multiplying that by the maximum # of lines you want, then plugging that into the height of the size you are constraining yourself to. It'd probably look like this:

然后将其乘以您想要的最大行数,然后将其插入您限制自己的大小的高度。它可能看起来像这样:

_price = [[UILabel alloc] init];
_price.text = myPriceValue;
_price.lineBreakMode = UILineBreakModeWordWrap;
_price.numberOfLines = 3;
_price.backgroundColor = [UIColor clearColor];
_price.textColor = TTSTYLEVAR(colorPrice);
CGFloat lineHeight = [_price.text sizeWithFont:_price.font].height;
CGSize priceSize = [_price.text sizeWithFont:_price.font
        constrainedToSize:CGSizeMake(maxWidth, lineHeight * _price.numberOfLines)
        lineBreakMode:UILineBreakModeWordWrap];

Don't use this if you ever set number of lines to 0 as your max height will be 0 in that case; you should use CGFLOAT_MAX then.

如果您曾经将行数设置为 0,请不要使用它,因为在这种情况下您的最大高度将为 0;那么你应该使用 CGFLOAT_MAX 。

回答by Felix

Use the UILabel's sizeToFit instead of sizeWithFont: to layout a multi-line UILabel, since sizeWithFont: will truncate the string (see apple docs). The following code reduces the font size of a label until the text fit into a the specified size... multiple lines of text will be used as soon as they fit into the specified height:

使用 UILabel 的 sizeToFit 而不是 sizeWithFont: 来布局多行 UILabel,因为 sizeWithFont: 将截断字符串(参见苹果文档)。以下代码减小了标签的字体大小,直到文本适合指定的大小……多行文本将在适合指定的高度后立即使用:

-(void)setFontSizeOfMultiLineLabel: (UILabel*)label 
        toFitSize: (CGSize) size 
        forMaxFontSize: (CGFloat) maxFontSize 
        andMinFontSize: (CGFloat) minFontSize 
        startCharacterWrapAtSize: (CGFloat)characterWrapSize{

CGRect constraintSize = CGRectMake(0, 0, size.width, 0);
label.frame = constraintSize;
label.lineBreakMode = UILineBreakModeWordWrap;
label.numberOfLines = 0; // allow any number of lines

for (int i = maxFontSize; i > minFontSize; i--) {

    if((i < characterWrapSize) && (label.lineBreakMode == UILineBreakModeWordWrap)){
        // start over again with lineBreakeMode set to character wrap 
        i = maxFontSize;
        label.lineBreakMode = UILineBreakModeCharacterWrap;
    }

    label.font = [label.font fontWithSize:i];
    [label sizeToFit];
    if(label.frame.size.height < size.height){
        break;
    }       
    label.frame = constraintSize;
  } 
}

Call this with a label that has your favorite text and font:

使用带有您最喜欢的文本和字体的标签来调用它:

UILabel *label = [[UILabel alloc] initWithFrame: CGRectZero];   
label.backgroundColor = [UIColor clearColor];   
label.textColor = [UIColor whiteColor];
label.text = text;
label.font = [UIFont fontWithName: @"Helvetica" size: 16];
[self setFontSizeOfMultiLineLabel: label toFitSize: CGSizeMake(200, 44) forMaxFontSize: 16 andMinFontSize: 8 startCharacterWrapAtSize: 11]; 

The startCharacterWrapAtSize parameter lets you choose to use characterWrap starting at the giving font size. This should save space in the case wordWrap would use really small fonts.

startCharacterWrapAtSize 参数允许您选择从指定字体大小开始使用 characterWrap。在 wordWrap 使用非常小的字体的情况下,这应该可以节省空间。

edit: bugfix

编辑:错误修正

回答by Amagrammer

Instead of trying to do it in one call, do something like this (pardon the pseudocode, it's late):

不要尝试在一次调用中完成,而是执行以下操作(请原谅伪代码,为时已晚):

NSString *s = _price.text;
UIFont *font = _price.font;
CGFloat fontSize = font.pointSize;

while (TRUE)
{
   CGSize priceSize = [s sizeWithFont: font constrainedToSize: 
       CGSizeMake(maxWidth, fontSize) lineBreakMode: UILineBreakModeWordWrap];

    if ( /* priceSize is satisfactory */ )
    {
        break; // Make sure this exits, eventually!!!
    }
    fontSize -= 1.0; // or a smaller decrement if you like
    font = // new, smaller font

}

回答by Tim Keating

The correct answer is, of course, you need to set numberOfLines to 0, which will cause the framework to compute the result with however many lines it needs. See also this question.

正确的答案当然是,您需要将 numberOfLines 设置为 0,这将导致框架使用它需要的任意多行来计算结果。另请参阅此问题

回答by Ed Marty

Of course it doesn't take it into account, since nothing being called or passed in has that information. You're strictly working with strings, sizes, and fonts. It's the label that has the number of lines in it.

当然它没有考虑到它,因为没有任何被调用或传入的信息。您严格地使用字符串、大小和字体。它是包含行数的标签。

I'm not sure what exactly your problem is; are you getting a size that's too tall or too short, or what? You can find out the number of lines of text by dividing the height of the result by the height of the font, which is the value of the ascender plus the descender, I believe.

我不确定你的问题到底是什么;你的尺码太高或太短,还是什么?你可以通过将结果的高度除以字体的高度来找出文本的行数,我相信这是上升部分加上下降部分的值。