How should I display detail view, with variable length strings?
I want to have a detail page that describes an object. It will have a title and a description, but the description can be any length. Is there any example's of this? I guess that a tableview all the rows have to be the same height? I could make it hard and use a variable number of cells and just make the top and bottom ones rounded, but this would be a lot of work seperating the string into character sized chunks. I just want it to look like a "real" app.
Thanks,
CP
This is a common problem. Tables can have variable height rows. Read the table view programming guide. Here's one example of how to do it. You'll have to figure out your own fudge factor based on the width of your tableviewcell.
Code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat result = 44.0f;
NSString* text = nil;
CGFloat width = 0;
CGFloat tableViewWidth;
CGRect bounds = [UIScreen mainScreen].bounds;
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation))
tableViewWidth = bounds.size.width;
else
tableViewWidth = bounds.size.height;
width = tableViewWidth - 110; // fudge factor
text = [self textForRow:indexPath.row];
if (text)
{
// The notes can be of any height
// This needs to work for both portrait and landscape orientations.
// Calls to the table view to get the current cell and the rect for the
// current row are recursive and call back this method.
CGSize textSize = { width, 20000.0f }; // width and height of text area
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:12.0f] constrainedToSize:textSize lineBreakMode:UILineBreakModeWordWrap];
size.height += 29.0f; // top and bottom margin
result = MAX(size.height, 44.0f); // at least one row
}
return result;
}
Thanks for the info, and it works great and saved me a lot of hasel. So now I need to get the text to wrap in the ViewCell. How do I get access to label that is part of default viewcell to set numberOfLines = 0? Or do I have to create a custom label?
Thanks,
CP
You should look at the TableViewSuite sample code as it does this. Basically you set the tag of the label when you create it and you get the subview back like this after you dequeue it:
This is really useful, and I got my cell height correct - but I need to make the label height the correct size too otherwise it won't show anything but the first row. The frame of my label is set to CGRectMake(75.0, 12.0, 200.0, 25.0) which works but it's only high enough to show the first row. If I make the label height larger than 25.0 it tries to center the text vertically in the label so labels that actually only have 1 row don't show the text, and the white space continues under the label. How can I tell the label frame to grow?
My frame is set in the layout subviews call of my cell subclass so I don't have access at that point to the text in the cell, so I can't just calculate the height of the text at that point.
sizeToFit will make a label adjust its frame to the correct size to hold its text. There's a gotcha that if the text is empty @"" sizeToFit will set the frame size to empty. All further calls to sizeToFit will not make the frame bigger anymore. To fix this you need to set the frame to some real size, like the original frame size, before calling sizeToFit.
Obviously there's no sense in trying to calculate the size of a label if it doesn't yet have the text that it's going to display. Set the text and then call layoutSubviews.
Obviously there's no sense in trying to calculate the size of a label if it doesn't yet have the text that it's going to display. Set the text and then call layoutSubviews.
This is what I ended up doing, and it worked perfectly. I messed around with sizeToFit and it just wasn't working right no matter what I did, so I ended up measuring the size manually and setting it using that value. Worked like a champ.
This is what I ended up doing, and it worked perfectly. I messed around with sizeToFit and it just wasn't working right no matter what I did, so I ended up measuring the size manually and setting it using that value. Worked like a champ.
I am having some trouble following what your saying here....
so I set up the cell.. and do [cell setText:someText]; then how do I measure the cells height and what do I do once I have that height? I assume that I am not using heightForRowAtIndexPath. Can anyone provide a quick snip of code for me to look at?
What is layoutSubviews and how to I use it? I tried looking for it in the doc.
I am having some trouble following what your saying here....
so I set up the cell.. and do [cell setText:someText]; then how do I measure the cells height and what do I do once I have that height? I assume that I am not using heightForRowAtIndexPath. Can anyone provide a quick snip of code for me to look at?
What is layoutSubviews and how to I use it? I tried looking for it in the doc.
You have two problems to solve here. You have to tell the table view the height of the cell, and you need to set up the subviews of the cell to the right heights.
To set the cell, you need to implement the method heightForRowAtIndexPath as you say. That method should be in your table view controller.
You also need to adjust the size of the subviews in your cell for the text.
What I did was to add a getHeightOfText and cellHeightWithText CLASS methods to my custom cell class. They are class methods because I want to be able to use the same methods in the code for my custom cell, and in the heightForRowAtIndexPath handler in my tableViewController. The logic that determines how tall a cell should be really belongs in my custom cell class, but the system asks the view controller. Creating a class method lets my heightForRowAtIndex path method ask the cell class how tall the cell should be.
The heightForRowAtIndexPath method in the table view controller is called before a cell has been set up, so it doesn't have access to an instance of a cell object. It asks my custom cell class "How tall should a cell be to display the following text?"
I don't use the label view in a default cell. instead I added my own UILabel to the cell. I added a setText method to the cell. The setText method uses the getHeightOfText class method to figure out the height of the text, and sets the frame of my text view accordingly.
In answer to your other question, layoutSubviews is an optional method for UIView that lets a view move and size it's subviews. If you have a cell with a variety of components (a couple of labels, an image, etc.) then the layoutSubviews method is a good place to put the logic that adjusts the size and location of the different parts of your cell based on the size and placement of the different parts of the cell.
@pcmofo, All you need to do is implement heightForRowAtIndexPath like I showed earlier in the thread. You'll need to modify the width in that code to adjust the fudge factor.
If your cell is so simple that you don't add any subviews then there's no need to do anything else.
In the case where you've added a Label and you're adding your text to the label you also, in most cases, won't need to do anything else. UILabel can be configured to adjust its own height based on the text that's added to it, and you should also set the autoResizingMask to flexibleWidth and height. That way the height of the label will be automatically adjusted when the height of the row is specified by your code.
I was just trying out the code above and the resizing of my cells worked great. But I am still having troubles resizing my labels so that I can see all lines and not only the first one.
The text Sizes of my labels seem to be ok..but I still dont see any changes in the numbers of lines I can actually see. I tried working with layoutSubviews and SizeToFit..both with no success.
Help would be greatly appreciated
Andre
Last edited by razorzerox; 01-25-2009 at 05:35 PM.
Set the number of lines to zero, like the header and docs explain.
Don't adjust the height of the label in cellForRowAtIndexPath. Implement heightForRowAtIndexPath: like I mention upthread.
Set the autoresizeMask for flexible height.
I actually implemented the heightForRowAtIndexPath method as you posted above but that only got my cells to the right height. I thought you had to somehow resize the labels in the cells as well but I guess this is done automatically by this autoresizingMask behaviour.
EDIT: It worked..thank you so much PhoneyDeveloper.
Last edited by razorzerox; 01-27-2009 at 04:55 AM.
CGSize textSize = { width, 20000.0f };// width and height of text area
can any one please tell me why 20000.0f is used as the height ?? when i try to use the above code snippet , the cell height isnt proper , for text with 1 line it wroks fine , but 2 - 3 lines the cell size is too big.
CGSize textSize = { width, 20000.0f };// width and height of text area
can any one please tell me why 20000.0f is used as the height ?? when i try to use the above code snippet , the cell height isnt proper , for text with 1 line it wroks fine , but 2 - 3 lines the cell size is too big.
vijayeta,
The idea is to create a CGSize that's as wide as your text field, but very tall. Then you call the NSString method -sizeWithFont and ask the string how tall it would be at the specified font and field width. To calculate cell height you then need to add the origin.y of the text field, plus any space you need below the text field, to get the final cell height.
Here's a snippet of the code I use in my heightForRowAtIndexPath method:
I'm trying to do the simplest case of a non-customized cell with multiple text rows and can't get it to work.
I have implemented tableView:cellForRowAtIndexPath and heightForRowAtIndexPath: as suggested above, and tried setting the cell autoresizingmask, the autoresizing mask on the cells contentview, the line wrap mode, and everything else I can think of to no avail.
The box does seem to resize (I am in grouped mode with 1 cell and 1 group) but the text doesn't wrap. I am not using a custom label.
I'm trying to do the simplest case of a non-customized cell with multiple text rows and can't get it to work.
I have implemented tableView:cellForRowAtIndexPath and heightForRowAtIndexPath: as suggested above, and tried setting the cell autoresizingmask, the autoresizing mask on the cells contentview, the line wrap mode, and everything else I can think of to no avail.
The box does seem to resize (I am in grouped mode with 1 cell and 1 group) but the text doesn't wrap. I am not using a custom label.
Help!
I had the same problem. You need to add:
Code:
[myLabel setNumberOfLines:0];
Which will allow the label to wrap to separate lines. Hope that helps.
I am not using a custom label, how to I get at the label in the cell? Or do I need to use a custom label and add it?
Yes, I would leave the cell.text label alone and just create your own, then add it to the cell's subview. This way you can customize the properties of your new label without headache.
Yes, I would leave the cell.text label alone and just create your own, then add it to the cell's subview. This way you can customize the properties of your new label without headache.
I tried that, and now I have to specify the height of the label. I can get it to wrap but only to the height of the label. I am giving up and figuring something else out.
Hard to believe something so simple can be so difficult, I must be missing something. I am just trying to put some text in a single grouped table view cell!
I tried that, and now I have to specify the height of the label. I can get it to wrap but only to the height of the label. I am giving up and figuring something else out.
Hard to believe something so simple can be so difficult, I must be missing something. I am just trying to put some text in a single grouped table view cell!
The idea is to use the same sizeWithFont method described earlier in this thread to calculate the height that the label would need to be to show all of the text. This calculated height is what you put in for the label's height value.
This is a common problem. Tables can have variable height rows. Read the table view programming guide. Here's one example of how to do it. You'll have to figure out your own fudge factor based on the width of your tableviewcell.
Code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat result = 44.0f;
NSString* text = nil;
CGFloat width = 0;
CGFloat tableViewWidth;
CGRect bounds = [UIScreen mainScreen].bounds;
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation))
tableViewWidth = bounds.size.width;
else
tableViewWidth = bounds.size.height;
width = tableViewWidth - 110; // fudge factor
text = [self textForRow:indexPath.row];
if (text)
{
// The notes can be of any height
// This needs to work for both portrait and landscape orientations.
// Calls to the table view to get the current cell and the rect for the
// current row are recursive and call back this method.
CGSize textSize = { width, 20000.0f }; // width and height of text area
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:12.0f] constrainedToSize:textSize lineBreakMode:UILineBreakModeWordWrap];
size.height += 29.0f; // top and bottom margin
result = MAX(size.height, 44.0f); // at least one row
}
return result;
}
Thanks its help me lot....
__________________
Check this Jumping Jack
Hope u will enjoy it