iOS 7中sizeWithAttributes:替代了sizeWithFont:constrainedToSize,用于计算文本大小。

134

如何从新的iOS 7方法sizeWithAttributes返回多行文本CGSize?

我希望这个方法会产生与sizeWithFont:constrainedToSize相同的结果。

NSString *text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eu urna quis lacus imperdiet scelerisque a nec neque. Mauris eget feugiat augue, vitae porttitor mi. Curabitur vitae sollicitudin augue. Donec id sapien eros. Proin consequat tellus in vehicula sagittis. Morbi sed felis a nibh hendrerit hendrerit. Lorem ipsum dolor sit."

CGSize textSize = [text sizeWithAttributes:@{ NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Light" size:16.0] }];

该方法仅适用于生成单行文本的高度。


看一下这个:http://stackoverflow.com/questions/18673176/sizewithfontconstrainedtosizelinebreakmode-deprecated/19137272?noredirect=1#19137272 - user1445205
6
和我使用相同的字体,点个赞 :) - Lescai Ionel
9个回答

297

那么你可以尝试这个:

NSDictionary *attributes = @{NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue" size:14]};
// NSString class method: boundingRectWithSize:options:attributes:context is
// available only on ios7.0 sdk.
CGRect rect = [textToMeasure boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX)
                                          options:NSStringDrawingUsesLineFragmentOrigin
                                       attributes:attributes
                                          context:nil];

4
这是我第一次看到用于字典的符号@{...},它叫什么名字? - Martin Berger
4
兄弟,我几乎对 Stack Overflow 失去了信心,但是我来到了这里。 - NSPunk
21
哇,新的 sizeWithFont:constrainedToSize: 方法比被弃用的原始方法更加晦涩难懂。苹果一定是真的讨厌我们。不管怎样,点赞。 - aroth
1
为什么你使用 MAXFLOAT 而不是 CGFLOAT_MAX - Julian F. Weinert
19
快速版本: let size = textToMeasure.boundingRect(with: CGSize(width: width, height: CGFloat.greatestFiniteMagnitude), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: attrs, context: nil).size - mdziadkowiec
显示剩余7条评论

23

这是我完成它的方法:

    // Get a font to draw it in
UIFont *font = [UIFont boldSystemFontOfSize: 28];

CGRect textRect;
NSDictionary *attributes = @{NSFontAttributeName: font};

// How big is this string when drawn in this font?
textRect.size = [text sizeWithAttributes:attributes];

// Draw the string
[text drawInRect:textRect withAttributes:attributes];

2
如果一个长字符串应该在行尾断开,那么这种方法就不起作用。请参考elio.d的答案,那个是正确的。 - Julian F. Weinert

4
这里是我处理这两种情况的方法,放在 NSString 类别中。
- (CGSize) sizeWithFontOrAttributes:(UIFont *) font {
    if (IS_IOS7) {
        NSDictionary *fontWithAttributes = @{NSFontAttributeName:font};
        return [self sizeWithAttributes:fontWithAttributes];
    } else {
        return [self sizeWithFont:font];
    }
}

3

对于 Xamarin.iOS:

UIFont descriptionLabelFont =  UIFont.SystemFontOfSize (11);
NSString textToMeasure = (NSString)DescriptionLabel.Text;

CGRect labelRect = textToMeasure.GetBoundingRect (
    new CGSize(this.Frame.Width, nfloat.MaxValue), 
    NSStringDrawingOptions.UsesLineFragmentOrigin, 
    new UIStringAttributes () { Font = descriptionLabelFont }, 
    new NSStringDrawingContext ()
);

3

Swift 2.3:

let attributes = [NSFontAttributeName:UIFont(name: "HelveticaNeue", size: 14)]
let rect = NSString(string: textToMeasure).boundingRectWithSize(
        CGSizeMake(width, CGFLOAT_MAX), 
        options: NSStringDrawingOptions.UsesLineFragmentOrigin, 
        attributes: attributes, context: nil)

Swift 4:

let attributes = [NSFontAttributeName:UIFont(name: "HelveticaNeue", size: 14)]
let rect = NSString(string: textToMeasure).boundingRect(
                    with: CGSize(width: width, height: CGFloat.greatestFiniteMagnitude),
                    options: NSStringDrawingOptions.usesLineFragmentOrigin,
                    attributes: attributes as [NSAttributedString.Key : Any], context: nil)

2

如果您已经设置了标签的文本、字体、行数和宽度,此方法将返回标签的大小:

myLabel.numberOfLines = 0;

CGSize size = [myLabel sizeThatFits:CGSizeMake(myLabel.frame.size.width, CGFLOAT_MAX)];`

1
作为替代方案,如果您正在查看 UITextView,您总是可以使用 NSLayoutManager 方法:
CGSize textSize = [textView.layoutManager usedRectForTextContainer:textView.textContainer].size;

你也可以通过以下方式找到给定字体的行高:

UIFont *font;
CGFloat lineHeight = font.lineHeight;

0
CGSize stringsize = [lbl.text sizeWithAttributes:
                         @{NSFontAttributeName:[UIFont fontWithName:FontProximaNovaRegular size:12.0]}];


CGSize adjustedSize = CGSizeMake(ceilf(stringsize.width), ceilf(stringsize.height));

使用ceilf方法来正确处理


0
作为新用户,我无法在@testing的答案下发表评论,但为了使他的答案(针对xamarin.ios)更有用,
我们可以返回一个CGRect,并仅使用高度参数来定位我们要定位的GUI项,例如UIButton等。将我们需要的任何参数传递如下:
    public CGRect GetRectForString(String strMeasure, int fontSize, nfloat guiItemWidth)
    {
        UIFont descriptionLabelFont =  UIFont.SystemFontOfSize (fontSize);
        NSString textToMeasure = (NSString)strMeasure;

        CGRect labelRect = textToMeasure.GetBoundingRect (
            new CGSize(guiItemWidth, nfloat.MaxValue), 
            NSStringDrawingOptions.UsesLineFragmentOrigin, 
            new UIStringAttributes () { Font = descriptionLabelFont }, 
            new NSStringDrawingContext ()
        );

        return labelRect;
    }

        header_Revision.Frame = new CGRect (5
                                            , verticalAdjust
                                            , View.Frame.Width-10
                                            , GetRectForString( header_Revision.Title(UIControlState.Normal)
                                                              , 18
                                                              , View.Frame.Width-10 ).Height
                                            );

这实际上应该是属于测试 Xamarin.IOS 的漂亮代码 :) 希望对任何人有所帮助 :) - Matt
当您的声望更高时,像这样的评论通常会附加到帖子中。由于您还没有达到该级别,因此感谢您提供额外的数据,并欢迎您来到 Stack Overflow。 - Stuart Siegler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接