I'd like to add my thoughts since I had exactly the same problem.
I was using UITextView
since it had nicer text alignment (justify, which at the time was not available in UILabel
), but in order to "simulate" non-interactive-non-scrollable UILabel
, I'd switch off completely scrolling, bouncing, and user interaction.
Of course, problem was that text was dynamic, and while width would be fixed, height should be recalculated every time I'd set new text value.
boundingRectWithSize
didn't work well for me at all, from what I could see, UITextView
was adding some margin on top which boundingRectWithSize
would not get into a count, hence, height retrieved from boundingRectWithSize
was smaller than it should be.
Since text was not to be updated rapidly, it's just used for some information that may update every 2-3 seconds the most, I've decided following approach:
/* This f is nested in a custom UIView-inherited class that is built using xib file */
-(void) setTextAndAutoSize:(NSString*)text inTextView:(UITextView*)tv
{
CGFloat msgWidth = tv.frame.size.width; // get target's width
// Make "test" UITextView to calculate correct size
UITextView *temp = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, msgWidth, 300)]; // we set some height, really doesn't matter, just put some value like this one.
// Set all font and text related parameters to be exact as the ones in targeted text view
[temp setFont:tv.font];
[temp setTextAlignment:tv.textAlignment];
[temp setTextColor:tv.textColor];
[temp setText:text];
// Ask for size that fits :P
CGSize tv_size = [temp sizeThatFits:CGSizeMake(msgWidth, 300)];
// kill this "test" UITextView, it's purpose is over
[temp release];
temp = nil;
// apply calculated size. if calcualted width differs, I choose to ignore it anyway and use only height because I want to have width absolutely fixed to designed value
tv.frame = CGRectMake(tv.frame.origin.x, tv.frame.origin.y, msgWidth, tv_size.height );
}
*Above code is not directly copied from my source, I had to adjust it / clear it from bunch of other stuff not needed for this article. Don't take it for copy-paste-and-it-will-work-code.
Obvious disadvantage is that it has alloc and release, for each call.
But, advantage is that you avoid depending on compatibility between how boundingRectWithSize draws text and calculates it's size and implementation of text drawing in UITextView
(or UILabel
which also you can use just replace UITextView
with UILabel
). Any "bugs" that Apple may have are this way avoided.
P.S. It would seem that you shouldn't need this "temp" UITextView
and can just ask sizeThatFits
directly from target, however that didn't work for me. Though logic would say it should work and alloc/release of temporary UITextView
are not needed, it did not. But this solution worked flawlessly for any text I would set in.
lineBreakMode
? – Hines