Nsattributedstring Boundingrect Returns Wrong Height

boundingRectWithSize for NSAttributedString returning wrong size

Looks like you weren't providing the correct options. For wrapping labels, provide at least:

CGRect paragraphRect =
[attributedText boundingRectWithSize:CGSizeMake(300.f, CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
context:nil];

Note: if the original text width is under 300.f there won't be line wrapping, so make sure the bound size is correct, otherwise you will still get wrong results.

NSAttributedString boundingRect returns wrong height

I found that this solution works. Note that if you don't set the lineFragmentPadding to 0, it produces the same (wrong) results as boundingRect.

extension NSAttributedString {
func sizeFittingWidth(_ w: CGFloat) -> CGSize {
let textStorage = NSTextStorage(attributedString: self)
let size = CGSize(width: w, height: CGFloat.greatestFiniteMagnitude)
let boundingRect = CGRect(origin: .zero, size: size)

let textContainer = NSTextContainer(size: size)
textContainer.lineFragmentPadding = 0

let layoutManager = NSLayoutManager()
layoutManager.addTextContainer(textContainer)

textStorage.addLayoutManager(layoutManager)

layoutManager.glyphRange(forBoundingRect: boundingRect, in: textContainer)

let rect = layoutManager.usedRect(for: textContainer)

return rect.integral.size
}
}

NSAttributedString size() method returns incorrect width

For future reference: I figured out the issue. When using attributedTitle, it's important to specify the font of the button, so that attributedString.size() can calculate the necessary width correctly. I assumed that by default, calculations are based on the default font for NSButton but apparently that was incorrect. See my commit for more details.

NSString boundingRectWithSize slightly underestimating the correct height - why?

I had the same Problem. I found the following in the Documentation:

To correctly draw and size multi-line text, pass
NSStringDrawingUsesLineFragmentOrigin in the options parameter.

This method returns fractional sizes (in the size component of the
returned CGRect); to use a returned size to size views, you must raise
its value to the nearest higher integer using the ceil function.

So this solved it for me:

CGRect rect = [myLabel.text boundingRectWithSize:CGSizeMake(myLabel.frame.size.width, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName: myLabel.font}
context:nil];
rect.size.width = ceil(rect.size.width);
rect.size.height = ceil(rect.size.height);

Update (Swift 5.1)

An alternative Swift way to do this would be:

let size = myLabel.text!.size(
withAttributes: [.font: myLabel.font!]
)
let rect = CGSize(
width: ceil(size.width),
height: ceil(size.height)
)

See this answer for an Objective-C example.

How to get height for NSAttributedString at a fixed width

The answer is to use

- (void)drawWithRect:(NSRect)rect options:(NSStringDrawingOptions)options
but the rect you pass in should have 0.0 in the dimension you want to be unlimited (which, er, makes perfect sense). Example here.



Related Topics



Leave a reply



Submit