Code, Code, Revolution!
Just starting with a new language and new framework you always run into problems that you never thought would be a problem. I’ve encountered the problem of finding out the height/width of text when drawn on screen when I was working with a Java applet. Now that I’m working on my GPS and internet aware iPhone app, together with my good friend since preschool and now colleague Hampus at Avantime, we consume a web service which serves us information. Of course, when fetching information from others you seldom know how much information they will send you. Working with a competent device like the iPhone I was surprised how much time I spent searching for the proper way to do it. When looking at the API reference I thought that setting the number of lines to 0 would do the trick, which it doesn’t. I tried everything I could find in the API reference but nothing would produce the multiline label I wanted. In our application we present the information in a nice UITableView, just like the Facebook application does (Facebook 2.0 application is awesome btw!). Eventually I found the method sizeWithFont in NSString which does exactly what I want. Here’s my static method that I will return the appropriate height for a label with a given width, font and line break mode:
+(float) calculateHeightOfTextFromWidth:(NSString*) text: (UIFont*)withFont: (float)width :(UILineBreakMode)lineBreakMode { [text retain]; [withFont retain]; CGSize suggestedSize = [text sizeWithFont:withFont constrainedToSize:CGSizeMake(width, FLT_MAX) lineBreakMode:lineBreakMode]; [text release]; [withFont release]; return suggestedSize.height; }
What this method does is return the appropriate size of a drawn on the screen, however it doesn’t return a wider or taller size than constrain it to. Therefore I give it the maximum size of a float (which is a constant) for height and it will return the appropriate size.
Making the entire scrollable view with a dynamic UITableView with dynamic height on different cells was quite a challenge. I’ll share some thoughts and our solution for that in the future.
With this blog I try to provide useful tips and solutions for programming .NET, Objective-C and more. My name is Björn Sållarp, and I love writing code.
sEnC
October 28th, 2008 at 5:11 am
Thanksmate. This was extremely handy for me.
THANKS!
The address field in Mail is UITextField? - iPhone Dev SDK Forum
November 10th, 2008 at 1:10 pm
[...] For a multiline text we need UITextView and we have to calculate the height of the text. here is a link that show you how to do this: Autosizing UILabel for a certain # of lines. – iDevKit or this link: iPhone dev – UILabel multiline and dynamic height [...]
johnny
December 31st, 2008 at 11:18 pm
Thanks for good post
Smolinski
May 12th, 2009 at 1:39 pm
Could you post a small app with a tableView where this is done as an example? I’m a beginner :]
Smolinski
May 12th, 2009 at 2:55 pm
If copy that code and place it in my class. But if I have a switch for each row in my table, how do i write to get the label to expand?
Björn Sållarp
May 12th, 2009 at 8:36 pm
The method is static, so you can add it to an existing/create a util-class and call it from anywhere. I don’t really have time to create a demo for this anytime soon, sorry.
Smolinski
May 13th, 2009 at 8:54 am
It’s ok, I understand that
Thank you anyway..
miscousi
May 18th, 2009 at 9:23 am
i’ve added the code in an existing class of mine. How do i call the method if i want to use it in a tableView where i use a switch like this:
switch (indexPath.row) {
case 0: {
cell.title = @”test”;
cell.data = test;
} break;
case 1: {
cell.title = @”test”;
cell.data = test;
} break;
case 2: {
cell.title = @”test”;
cell.data = test;
} break;
etc etc.
miscousi
May 19th, 2009 at 4:01 pm
Hm.. am i doing totally wrong or is it a way to call this method like I describe it ?:]
Björn Sållarp
May 19th, 2009 at 9:16 pm
I have added the method to a utils class but you can add it to your table view class or whatever. This is how I call the method in my TableCell class:
- (void)setValueAndCalculateHeight:(NSString *)text
{
self.value.text = text;
CGRect frame = value.frame;
frame.size.height = [MLUtils calculateHeightOfTextFromWidth:self.value.text :self.value.font :frame.size.width :self.value.lineBreakMode];
//If the new height is larger then min height we add the frame to description label
if(frame.size.height>VALUE_MIN_HEIGHT)
{
self.value.frame = frame;
}
}
So to set the text in the cell i pass it to my function which will call the static calculateHeightOfTextFromWidth method in my MLUtils class. The height is used to adjust the frame of the cell. Hope this helps. Good luck!
miscousi
May 25th, 2009 at 11:51 am
My second week with this, sry.
But i guess that “value” is your label that you use later in your tableView?
But when i’m going to use my label in my switch as I describe earlier like this:
switch (indexPath.row) {
case 0: {
cell.value.text = myData;
} break;
I get the message: request for meber “value” in something not a structure or a union.?
miscousi
May 27th, 2009 at 8:42 am
You don’t have to answer or show this or my latest reply. I’ve solved it myself, thanks for help!
Shilpa
October 7th, 2009 at 1:20 pm
Hi! Above tip for multiline label height calculation helped me a lot. Thank you.
Rob Mathews
December 24th, 2009 at 2:58 am
Has someone worked through enabling functionality for “heightForRowAtIndexPath” using the current source code. If yes, please post the changes/updates that need to be made.
iPhoneDev
January 1st, 2010 at 10:27 am
Hi Smolinski, Rob Mathews
I worked for for “heightForRowAtIndexPath” of tableview.
You can take idea from here
http://urenjoy.blogspot.com/2009/07/dynamic-multiline-label-custom-font.html