不推荐使用sizeWithFont方法。boundingRectWithSize返回意外值


82

在iOS7中,sizeWithFont它已弃用,因此我正在使用boundingRectWithSize(它返回CGRect值)。我的代码:

 UIFont *fontText = [UIFont fontWithName:[AppHandlers zHandler].fontName size:16];
                    // you can use your font.

 CGSize maximumLabelSize = CGSizeMake(310, 9999);

 CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                             options:NSStringDrawingUsesLineFragmentOrigin
                             attributes:@{NSFontAttributeName:fontText}
                             context:nil];

 expectedLabelSize = CGSizeMake(textRect.size.width, textRect.size.height);

在中textRect,我得到的尺寸大于maximumLabelSize使用的尺寸,与使用时的尺寸不同sizeWithFont。我该如何解决这个问题?


我正在使用所有字体(不仅是系统字体或Helvetica)遇到此问题。
尼拉夫·in那

你有什么想法吗?
尼拉夫·in那

字体名称,文本和不匹配大小的具体示例可能会有所帮助。
Eiko

我曾经在iOS6中使用CTFramesetterSuggestFrameSizeWithConstraints来计算attributedString的高度,该高度始终返回正确的高度。在iOS7中,CTFramesetterSuggestFrameSizeWithConstraints和boundingRectWithSize都给我一个错误的高度结果。我敢打赌,这是iOS7中引入的错误,似乎还没有解决方案。
阿诺德·唐

林也面临着同样的问题,最好使用tttattributedlabel
斯里兰卡。

Answers:


151

如何创建新标签并使用sizeThatFit:(CGSize)size??

UILabel *gettingSizeLabel = [[UILabel alloc] init];
gettingSizeLabel.font = [UIFont fontWithName:@"YOUR FONT's NAME" size:16];
gettingSizeLabel.text = @"YOUR LABEL's TEXT";
gettingSizeLabel.numberOfLines = 0;
gettingSizeLabel.lineBreakMode = NSLineBreakByWordWrapping;
CGSize maximumLabelSize = CGSizeMake(310, CGFLOAT_MAX);

CGSize expectSize = [gettingSizeLabel sizeThatFits:maximumLabelSize];

编辑:此较高代码不适用于ios 7及更高版本,因此请在下面使用:

CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                         options:NSStringDrawingUsesLineFragmentOrigin| NSStringDrawingUsesFontLeading
                         attributes:@{NSFontAttributeName:fontText}
                         context:nil];

当我在字符串中添加像(<OL>,<LI>)这样的HTML实体时,此方法不起作用。
尼拉夫·in那

请再次检查我的答案!我错过了numberOfLines属性!抱歉!
QuangHà13年

1
经过数小时的搜索,试验和死胡同,这是唯一适用于iOS7和Xamarin / Monotouch的解决方案
Michael Rodrigues

26
创建标签以计算字体大小?真浪费!
Ossir 2014年

13
@Ossir,您有更好的主意吗?
卢达2014年

36

也许您需要为此答案中建议的方法提供其他选项:

CGSize maximumLabelSize = CGSizeMake(310, CGFLOAT_MAX);
CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                                         options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                      attributes:@{NSFontAttributeName: fontText}
                                         context:nil];

3
看起来好像boundingRectWithSize坏了。我在iOS 7、7.1.1上进行了测试,但返回的结果不正确。
RaffAl 2014年

这对我不起作用,但是在NSAttributedString上使用boundingRectWithSize并将我的font属性添加到字符串上确实可以工作。
Sheepdogsheep

12
伙计们,不要忘了Apple声明:在iOS 7及更高版本中,此方法返回小数大小(在返回的CGRect的大小部分中);要使用返回的大小调整视图大小,必须使用ceil函数将其值提高到最接近的较大整数。
SoftDesigner 2014年

2
ceil对我来说还不够,但发现使用ceil并同时添加0.5可以达到目的
dwery

15

这是我的工作代码段:

NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:attributeDict];

NSString *headline  = [dict objectForKey:@"title"];  
UIFont *font        = [UIFont boldSystemFontOfSize:18];  
CGRect  rect        = [headline boundingRectWithSize:CGSizeMake(300, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];

CGFloat height      = roundf(rect.size.height +4)

我在计算出的高度上添加了4px,因为如果没有这些4px,则会丢失一行。

我在tableView中使用此代码段,并将“ height”添加到NSNumbers数组中,并且得到默认textLabel的正确单元格高度。

如果要在textLabel中的文本下留出更多空间,请再增加4个像素。

****更新****

我不同意“ 40px的宽度错误”,我大喊是缺少高度的4px,因为4px是字母和单行边界之间的默认默认高度。您可以使用UILabel进行检查,如果字体大小为16,则需要UILabel高度为20。

但是,如果您的最后一行没有“ g”或其中的任何内容,则该度量可能会错过4px的高度。

我用一种小方法重新检查了一下,我的标签的准确高度为20,40或60,而正确的宽度小于300px。

要支持iOS6和iOS7,可以使用我的方法:

- (CGFloat)heightFromString:(NSString*)text withFont:(UIFont*)font constraintToWidth:(CGFloat)width
{
    CGRect rect;

    float iosVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (iosVersion >= 7.0) {
        rect = [text boundingRectWithSize:CGSizeMake(width, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];
    }
    else {
        CGSize size = [text sizeWithFont:font constrainedToSize:CGSizeMake(width, 1000) lineBreakMode:NSLineBreakByWordWrapping];
        rect = CGRectMake(0, 0, size.width, size.height);
    }
    NSLog(@"%@: W: %.f, H: %.f", self, rect.size.width, rect.size.height);
    return rect.size.height;
}

****升级****

感谢您的评论,我按如下方式升级了功能。由于不推荐使用sizeWithFont,并且您会在XCode中收到警告,因此我添加了诊断编译代码以删除针对此特定函数调用/代码块的警告。

- (CGFloat)heightFromStringWithFont:(UIFont*)font constraintToWidth:(CGFloat)width
{
    CGRect rect;

    if ([self respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) {
        rect = [self boundingRectWithSize:CGSizeMake(width, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];
    }
    else {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
        CGSize size = [self sizeWithFont:font constrainedToSize:CGSizeMake(width, 1000) lineBreakMode:NSLineBreakByWordWrapping];
        rect = CGRectMake(0, 0, size.width, size.height);
#pragma GCC diagnostic pop
    }
    return ceil(rect.size.height);
}

除了4px主题:根据您使用的字体和字体粗细,该计算还返回不同的高度值。在我的情况下:字体大小为16.0的HelveticaNeue-Medium对一行返回20.0的行高,对两行返回39.0,对四行返回78px->每行缺少1px-从第2行开始-但您想要要使每行的fontsize + 4px行距都必须得到一个高度结果。
编码时请记住这一点!
我没有针对此“问题”的功能,但完成后我将更新此帖子。


1
您可能应该使用[text responsesToSelector:@selector(boundingRectWithSize:options:attributes:context :)],而不要检查浮点值。
萨玛2014年

1
最好使用ceil函数而不是+ 4pt,请看此答案stackoverflow.com/a/23563152/667483
surfrider 2015年

2

如果我理解正确,那么您正在使用boundingRectWithSize:就像获得sizeWithFont所获得的大小一样(这意味着您直接需要CGSize,而不是CGRect)?

这看起来像您在寻找什么:

在iOS 7中替换过时的sizeWithFont:吗?

他们使用sizeWithAttributes:来获取大小,以替代sizeWithFont。

您是否仍然使用类似的方法得到错误的尺寸:

UIFont *fontText = [UIFont fontWithName:[AppHandlers zHandler].fontName size:16];
                    // you can use your font.

expectedLabelSize = [myString sizeWithAttributes:@{NSFontAttributeName:fontText}];

但是如何使用CGSize maximumLabelSize = CGSizeMake(310,9999)?我需要正确的高度和宽度。
尼拉夫·in那

1
是否有任何属性告诉sizeWithAttributes:限制其宽度/高度?
尼拉夫·in那

抱歉,我不明白您的问题是什么。如果我理解正确,则希望使用字体大小来设置标签的大小,但不要超过最大高度。您说您可以使用sizeWithFont做到这一点,但是由于此方法已弃用,您想要一个替代方法,对吗?您应该能够像使用sizeWithFont:一样插入sizeWithAttribues:。使用sizeWithFont时如何限制标签大小?您可以使用sizeWithFont发布适合您的代码吗?
vinaut

2
他使用的是sizeWithFont:constrainedToSize:lineBreakMode:并且无法将constrainedToSize值传递给sizeWithAttributes。
zh。

2

@SoftDesigner的评论对我有用

CGRect descriptionRect = [description boundingRectWithSize:CGSizeMake(width, 0)
                                                       options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                                    attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:12]}
                                                       context:nil];
result = ceil(descriptionRect.size.height);

1

用于查找标签运行时大小的sizewithfont在iOS 7.0中已弃用,而您必须使用-boundingRectWithSize:options:attributes:context:方法

您可以像下面的代码一样使用它

CGSize constraint = CGSizeMake(MAXIMUM_WIDHT, TEMP_HEIGHT);
NSRange range = NSMakeRange(0, [[self.message body] length]);

NSDictionary *attributes = [YOUR_LABEL.attributedText attributesAtIndex:0 effectiveRange:&range];
CGSize boundingBox = [myString boundingRectWithSize:constraint options:NSStringDrawingUsesFontLeading attributes:attributes context:nil].size;
int numberOfLine = ceil((boundingBox.width) / YOUR_LABEL.frame.size.width);
CGSize descSize = CGSizeMake(ceil(boundingBox.width), ceil(self.lblMessageDetail.frame.size.height*numberOfLine));

CGRect frame=YOUR_LABEL.frame;
frame.size.height=descSize.height;
YOUR_LABEL.frame=frame;

在这里,您必须为最大长度指定宽度,以查找高度或宽度。

试试这个对我有用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.