How to get height for NSAttributedString at a fixed width

后端 未结 12 1075
萌比男神i
萌比男神i 2020-12-12 18:53

I want to do some drawing of NSAttributedStrings in fixed-width boxes, but am having trouble calculating the right height they\'ll take up when drawn. So far, I\'ve tried:

相关标签:
12条回答
  • 2020-12-12 19:37

    You might be interested in Jerry Krinock's great (OS X only) NS(Attributed)String+Geometrics category, which is designed to do all sorts of string measurement, including what you're looking for.

    0 讨论(0)
  • 2020-12-12 19:38

    I just wasted a bunch of time on this, so I'm providing an additional answer to save others in the future. Graham's answer is 90% correct, but it's missing one key piece:

    To obtain accurate results with -boundingRectWithSize:options: you MUST pass the following options:

    NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesDeviceMetrics|NSStringDrawingUsesFontLeading
    

    If you omit the lineFragmentOrigin one, you'll get nonsense back; the returned rect will be a single line high and won't at all respect the size you pass into the method.

    Why this is so complicated and so poorly documented is beyond me. But there you have it. Pass those options and it'll work perfectly (on OS X at least).

    0 讨论(0)
  • 2020-12-12 19:46

    On OS X 10.11+, the following method works for me (from Apple's Calculating Text Height document)

    - (CGFloat)heightForString:(NSAttributedString *)myString atWidth:(float)myWidth
    {
        NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:myString];
        NSTextContainer *textContainer = [[NSTextContainer alloc] initWithContainerSize:
            NSMakeSize(myWidth, FLT_MAX)];
        NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
        [layoutManager addTextContainer:textContainer];
        [textStorage addLayoutManager:layoutManager];
        [layoutManager glyphRangeForTextContainer:textContainer];
        return [layoutManager
            usedRectForTextContainer:textContainer].size.height;
    }
    
    0 讨论(0)
  • 2020-12-12 19:50

    Swift 4.2

    let attributedString = self.textView.attributedText
    let rect = attributedString?.boundingRect(with: CGSize(width: self.textView.frame.width, height: CGFloat.greatestFiniteMagnitude), options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil)
    print("attributedString Height = ",rect?.height)
    
    0 讨论(0)
  • 2020-12-12 19:52

    Use NSAttributedString method

    - (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context
    

    The size is the constraint on the area, the calculated area width is restricted to the specified width whereas the height is flexible based on this width. One can specify nil for context if that's not available. To get multi-line text size, use NSStringDrawingUsesLineFragmentOrigin for options.

    0 讨论(0)
  • 2020-12-12 19:52

    Not a single answer on this page worked for me, nor did that ancient old Objective-C code from Apple's documentation. What I finally did get to work for a UITextView is first setting its text or attributedText property on it and then calculating the size needed like this:

    let size = textView.sizeThatFits(CGSize(width: maxWidth, height: CGFloat.max))
    

    Works perfectly. Booyah!

    0 讨论(0)
提交回复
热议问题