Advertise Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Your First iPhone App
($1.99)

iPhone Code Generator
($9.99)

Calcuccino Programmers' Calculator
($2.99)

DataFon(Build Apps on Windows)
(free)

Infinote Pinboard for Todos and Notes
(free)

picplz
(free)

poG
($2.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 09-12-2008, 08:12 PM   #1 (permalink)
New Member
 
Join Date: Sep 2008
Posts: 3
Default 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
CptanPanic is offline   Reply With Quote
Old 09-12-2008, 11:28 PM   #2 (permalink)
New Member
 
Join Date: Sep 2008
Posts: 1,431
Default

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;
}
PhoneyDeveloper is offline   Reply With Quote
Old 09-13-2008, 07:58 AM   #3 (permalink)
New Member
 
Join Date: Sep 2008
Posts: 3
Default

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
CptanPanic is offline   Reply With Quote
Old 09-13-2008, 05:03 PM   #4 (permalink)
New Member
 
Join Date: Sep 2008
Posts: 1,431
Default

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:

Code:
// creation
	label = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 12.0f, 70.0f, 25.0f)];
	label.tag = LABEL_TAG;
	[cell.contentView addSubview:label];

// after dequeue
label = (UILabel *)[cell.contentView viewWithTag:LABEL_TAG];
PhoneyDeveloper is offline   Reply With Quote
Old 10-13-2008, 12:22 AM   #5 (permalink)
Registered Member
 
Join Date: Sep 2008
Posts: 159
Default

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.
Vortec4800 is offline   Reply With Quote
Old 10-13-2008, 09:10 AM   #6 (permalink)
New Member
 
Join Date: Sep 2008
Posts: 1,431
Default

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.
PhoneyDeveloper is offline   Reply With Quote
Old 10-13-2008, 01:10 PM   #7 (permalink)
Registered Member
 
Join Date: Sep 2008
Posts: 159
Default

Quote:
Originally Posted by PhoneyDeveloper View Post
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.
Vortec4800 is offline   Reply With Quote
Old 01-06-2009, 08:43 AM   #8 (permalink)
Registered Member
 
Join Date: Oct 2008
Posts: 91
Default

Quote:
Originally Posted by Vortec4800 View Post
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.

Last edited by pcmofo; 01-06-2009 at 08:53 AM.
pcmofo is offline   Reply With Quote
Old 01-13-2009, 04:26 PM   #9 (permalink)
Registered Member
 
Join Date: Oct 2008
Posts: 91
Default

I have still gotten no where with this.... can anyone help me out here?
pcmofo is offline   Reply With Quote
Old 01-13-2009, 06:47 PM   #10 (permalink)
Registered Member
 
Duncan C's Avatar
 
Join Date: Dec 2008
Location: Northern Virginia
Posts: 977
Default

Quote:
Originally Posted by pcmofo View Post
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.



Duncan C
WareTo
Duncan C is offline   Reply With Quote
Old 01-13-2009, 07:27 PM   #11 (permalink)
New Member
 
Join Date: Sep 2008
Posts: 1,431
Default

@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.
PhoneyDeveloper is offline   Reply With Quote
Old 01-25-2009, 08:13 AM   #12 (permalink)
Registered Member
 
Join Date: Jan 2009
Posts: 44
Default

hello everyone

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.

My cell should look like this:

germantext1, englishtranslation1
altgermantext, englishtranslation2
altgermantext2

Here is what I have implemented so far:
Code:
-(UITableViewCell *)tableView:(UITableView *)tableView
		cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
	static NSString *CellTableIdentifier = @"CellTableIdentifier";
	UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellTableIdentifier];
	CGFloat tableViewWidth;
		CGFloat width = 0;
	CGRect bounds = [UIScreen mainScreen].bounds;
	NSString *text1, *text2 = nil;
	
	if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation))
		tableViewWidth = bounds.size.width/2;
	else
		tableViewWidth = bounds.size.height/2;
	
	width = tableViewWidth - 90; //fudge factor
	
	NSDictionary *rowData = [self.matches objectAtIndex:indexPath.row];
	text1 = [rowData objectForKey:@"german"];
	text2 = [rowData objectForKey:@"english"];
	
	if (cell == nil) {
		
		
		CGSize textSize = {width, 20000.0f}; //width and height of text area
		
		//german height
		CGSize size1 = [text1 sizeWithFont:[UIFont systemFontOfSize:12.0f]
						 constrainedToSize:textSize lineBreakMode:UILineBreakModeWordWrap];
		//english height
		CGSize size2 = [text2 sizeWithFont:[UIFont systemFontOfSize:12.0f]
						 constrainedToSize:textSize lineBreakMode:UILineBreakModeWordWrap];

		CGRect cellFrame = CGRectMake(0,0,300,65);
		cell = [[[UITableViewCell alloc] initWithFrame:cellFrame
									   reuseIdentifier:CellTableIdentifier] autorelease];
		//CGRectmake(x,y,width,height)
		//Setting up the english and german labels manually
		CGRect germanRect = CGRectMake(0,10,140,size1.height);
		UILabel *germanLabel = [[UILabel alloc] initWithFrame:germanRect];
		// germanLabel.textAlignment = UITextAlignmentRight;
		germanLabel.tag =kGermanTag;
		[cell.contentView addSubview:germanLabel];
		[germanLabel release];

		CGRect englishRect = CGRectMake(150,10,140,size2.height);
		UILabel *englishLabel = [[UILabel alloc] initWithFrame:englishRect];
		// englishLabel.textAlignment = UITextAlignmentRight;
		englishLabel.tag =kEnglishTag;
		[cell.contentView addSubview:englishLabel];
		[englishLabel release];
	}
	
	// Setting the costum labels to the right data
	UILabel *germanLabel = (UILabel *)[cell.contentView viewWithTag:kGermanTag];
	germanLabel.text = [rowData objectForKey:@"german"];
	
	UILabel *englishLabel = (UILabel *)[cell.contentView viewWithTag:kEnglishTag];
	englishLabel.text = [rowData objectForKey:@"english"]; 
	
	return cell;
}
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.
razorzerox is offline   Reply With Quote
Old 01-26-2009, 05:31 PM   #13 (permalink)
Registered Member
 
Join Date: Jan 2009
Posts: 44
Default

I could really use some help on this one. My cell still only displays one line of text no matter how large I define the height of the label.
razorzerox is offline   Reply With Quote
Old 01-26-2009, 05:59 PM   #14 (permalink)
New Member
 
Join Date: Sep 2008
Posts: 1,431
Default

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.
PhoneyDeveloper is offline   Reply With Quote
Old 01-26-2009, 06:39 PM   #15 (permalink)
Registered Member
 
Join Date: Jan 2009
Posts: 44
Default

Quote:
Originally Posted by PhoneyDeveloper View Post
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.
razorzerox is offline   Reply With Quote
Old 01-29-2009, 05:05 AM   #16 (permalink)
New Member
 
Join Date: Nov 2008
Posts: 3
Default I too have similar issue

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 is offline   Reply With Quote
Old 01-29-2009, 06:35 AM   #17 (permalink)
Registered Member
 
Duncan C's Avatar
 
Join Date: Dec 2008
Location: Northern Virginia
Posts: 977
Default

Quote:
Originally Posted by vijayeta View Post
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:

Code:
	CGSize tempSize;
	CGSize theTextSize;
	tempSize.width = theTableWidth-(10+ 7 + kImageSize);
	tempSize.height = 9999;
	theTextSize = [theText sizeWithFont: theFont constrainedToSize: tempSize];
Duncan C is offline   Reply With Quote
Old 04-21-2009, 05:08 PM   #18 (permalink)
Registered Member
 
Join Date: Nov 2008
Posts: 142
Default

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!
john855 is offline   Reply With Quote
Old 04-22-2009, 02:12 AM   #19 (permalink)
Registered Member
 
Join Date: Sep 2008
Posts: 159
Default

Quote:
Originally Posted by john855 View Post
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.
Vortec4800 is offline   Reply With Quote
Old 04-22-2009, 11:12 AM   #20 (permalink)
Registered Member
 
Join Date: Nov 2008
Posts: 142
Default

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?
john855 is offline   Reply With Quote
Old 04-22-2009, 12:34 PM   #21 (permalink)
Registered Member
 
Join Date: Sep 2008
Posts: 159
Default

Quote:
Originally Posted by john855 View Post
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.
Vortec4800 is offline   Reply With Quote
Old 04-25-2009, 10:17 PM   #22 (permalink)
Registered Member
 
Join Date: Nov 2008
Posts: 142
Default

Quote:
Originally Posted by Vortec4800 View Post
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!
john855 is offline   Reply With Quote
Old 04-25-2009, 10:36 PM   #23 (permalink)
Registered Member
 
Join Date: Sep 2008
Posts: 159
Default

Quote:
Originally Posted by john855 View Post
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.
Vortec4800 is offline   Reply With Quote
Old 05-23-2010, 06:32 AM   #24 (permalink)
Registered Member
 
Join Date: Sep 2009
Posts: 90
Default

Quote:
Originally Posted by PhoneyDeveloper View Post
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
evana is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


» Advertisements
» Stats
Members: 51,375
Threads: 52,830
Posts: 225,478
Top Poster: BrianSlick (3,576)
Welcome to our newest member, darrentousignant
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 02:31 PM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0