UILabel's sizeToFit/sizeThatFits ignore the numberoflines property
Problem: Determine the size (number of lines) a UILabel
needs, assuming the width is 300 px. The string is longer, so I set the lineBreakMode
to UILineBreakModeWordWrap
and invoked sizeThatFits
to try to determine the size. But it gives a width of 457 px in a single line, rather than the expected 300px in two lines.
Please see:
CGSize available = CGSizeMake(300, INFINITY);
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 300, 400)] autorelease];
label.text = title;
label.lineBreakMode = UILineBreakModeWordWrap;
label.font = [UIFont fontWithName:kBoldFont size:kTitleFontSize];
label.numberOfLines = 3;
CGSize sizedtoFit = [label sizeThatFits:available];
But I find that the sizedtoFit variable has a width of 457 pixels and a height of 22 px, and the UI displays a single line with clipped text. I expect a width of 300 pixels, and a height of 44 px for two lines.
The UILabel doc for numberoflines says:
When the receiver is resized using the sizeToFit
method, resizing takes into account the value stored in this property. For example, if this property is set to 3, the sizeToFit
method resizes the receiver so that it is big enough to display three lines of text.
I tried various combinations of:
-
开发者_StackOverflow中文版
- Passing
CGRectZero
to the init function, passing 300x400 or 300 x infinity. - Setting the frame after creation rather than passing it to the
init
function. - Invoking
[sizeToFit]
and hoping it calculates the height assuming present width, but it doesn't. - Calling sizeToFit and then calling sizeThatFits`.
- Invoking
layoutIfNeeded
.
None of them works. What am I doing wrong, or is this is bad bug where the documentation and the framework implementation don't agree? Thanks.
I had the same problem, size that fits simply ignores the size... /: I ended up using:
CGRect textSize = [UILabel textRectForBounds:CGRectMake(0, 0, 300, CGFLOAT_MAX)
limitedToNumberOfLines:3];
Works like a charm... :)
The documentation says you shouldn't call it directly, but i've been using it for a while, with approved submitted apps, and everything is just awesome... :)
Have you tried the sizeWithFont: constrainedToSize: lineBreakMode:
method?
For example:
CGSize sizeToFit = [title sizeWithFont:label.font constrainedToSize:label.frame.size lineBreakMode:label.lineBreakMode];
I found Ian L's answer best using -sizeWithFont:constrainedToSize:lineBreakMode:
, unfortunately sizeWithFont: is deprecated under iOS7.
This is how sizeWithFont: works for a UILabel subclass in iOS7:
NSRange range = NSMakeRange(0, self.attributedText.length);
sizeToFit = [self.text boundingRectWithSize:self.bounds.size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:[self.attributedText
attributesAtIndex:0 effectiveRange:&range] context:nil].size;
This is all deprecated. Use boundingRectWithSize
I think you are getting unexpected results because you are not taking into consideration the UILabel
's font. Try the following:
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 300, 400)] autorelease];
label.text = title;
label.lineBreakMode = UILineBreakModeWordWrap;
label.font = [UIFont fontWithName:kBoldFont size:kTitleFontSize];
label.numberOfLines = 0;
CGSize size = [label.text sizeWithFont:label.font constrainedToSize:CGSizeMake(label.frame.size.width,FLT_MAX) lineBreakMode:UILineBreakModeWordWrap ];
label.frame = CGRectMake(label.frame.origin.x,label.frame.origin.y,label.frame.size.width,size.height);
There is no solution for ios5 for sizeToFit
. You may use other solutions like sizeWithFont
etc. In ios6, the issue is fixed. However, I have this workaround for my solutions:
int lineCount = myLabel.numberOfLines;
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
myLabel.numberOfLines = lineCount;
And it works. Beware that for my situation, width of my label is fixed and I only need sizeToFit for adjusting height.
精彩评论