I would like to have a tablew view with a behaviour similar to the iPhone Contacts app by Apple: a uitableviewcell with a uitextview inside, so that when I write in the uitextview, the uitextview increases its height, and so accordingly the uitableviewcell dynamically adjusts its height. I searched over the whole web, finding only partial solutions and lack of sample code!
please help me I am desperate
Tony
Looking at this,you need to be somewhat tricky. You need to calculate the height of the textView dynamically and based on the Height of the TextView,you need to return the Height for the cell..
It's very easy & somewhat Tricky..
This is the code by which you can calculate the size of string....
First get the size of String
NSString *label = @"Sample String to get the Size for the textView Will definitely work ";
CGSize stringSize = [label sizeWithFont:[UIFont boldSystemFontOfSize:15]
constrainedToSize:CGSizeMake(320, 9999)
lineBreakMode:UILineBreakModeWordWrap];
over here ....
NSLog(@"%f",stringSize.height);
Secondly dynamically create the textView in the cell..giving the stringSize.height
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
//}
NSDictionary *d=(NSDictionary *)[self.menuArray objectAtIndex:indexPath.section];
NSString *string = [d valueForKey:@"Description"];
CGSize stringSize = [string sizeWithFont:[UIFont boldSystemFontOfSize:15] constrainedToSize:CGSizeMake(320, 9999) lineBreakMode:UILineBreakModeWordWrap];
UITextView *textV=[[UITextView alloc] initWithFrame:CGRectMake(5, 5, 290, stringSize.height+10)];
textV.font = [UIFont systemFontOfSize:15.0];
textV.text=string;
textV.textColor=[UIColor blackColor];
textV.editable=NO;
[cell.contentView addSubview:textV];
[textV release];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *d=(NSDictionary *)[self.menuArray objectAtIndex:indexPath.section];
NSString *label = [d valueForKey:@"Description"];
CGSize stringSize = [label sizeWithFont:[UIFont boldSystemFontOfSize:15]
constrainedToSize:CGSizeMake(320, 9999)
lineBreakMode:UILineBreakModeWordWrap];
return stringSize.height+25;
}
After giving so much pain to my fingers,......I think this is enough code...& will surely help to solve your problem..
Good Luck
Create a custom UITableViewCell and add your UITextView to the cell's contentView.
In LayoutSubviews, set textView.frame to the cell's contentView.bounds (or do some other custom layout).
When the textView contents change (discovered via UITextViewDelegate), do two things:
1) call [tableView beginUpdates]; [tableView endUpdates];
This will force the table view to recalculate the height for all cells (will call tableView:heightForRowAtIndexPath:
). If your cell is the delegate for the textView then you'll have to figure out how to get a pointer to the tableView, but there are a few ways to achieve that. Or you could make the delegate your view controller...
2) when tableView:heightForRowAtIndexPath:
is called for this cell, return the textView.contentSize.height
. You can get your cell from here by calling [tableView cellForRowAtIndexPath];
Or if you just have one of these cells then cache a pointer to it in your viewController.
The only issue I found with the accepted answer was that we are allocating the UITextView each and every time. I found that this raised issues with typing into the view and having the text updating immediately and also keeping the view as first responder. When I tried to reload the cell with the new height it would then try to add a new textView.
Because of this I found a slightly different method to achieve the same goal. Hopefully this different take might help people who are struggling to implement the above code.
1) In the header file define a variable for the height of the text and the textView:
UITextView * _textView;
NSInteger _textHeight;
Setting a variable means that we can load the view to be a certain height if we are loading text into the textView and also reduces the complexity.
2) Load the text view and add it to our cell
_textView = [[UITextView alloc] init];
_textView.delegate = self;
_textView.returnKeyType = UIReturnKeyDone;
_textView.font = [UIFont fontWithName:@"Helvetica" size:16];
if (![_user metaStringForKey:bBioKey].length) {
_textView.text = @"Placeholder text";
_textView.textColor = [UIColor lightGrayColor];
}
- (UITableViewCell *)tableView:(UITableView *)tableView_ cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath == 0) { // Add logic to choose the correct cell
if (_textView.superview != cell) {
[cell addSubview:_textView];
_textView.keepTopInset.equal = KeepRequired(7);
_textView.keepBottomInset.equal = KeepRequired(7);
_textView.keepRightInset.equal = KeepRequired(10);
_textView.keepLeftInset.equal = KeepRequired(70);
}
}
}
}
Using keeplayout has enabled us to keep our textfield to always stay the same height as the cell. We are also only ever adding our UITextView once.
3) Add the code to calculate the height of the text
- (NSInteger)getHeightOfBio: (NSString *)text {
UILabel * gettingSizeLabel = [[UILabel alloc] init];
gettingSizeLabel.font = [UIFont fontWithName:@"Helvetica" size:16];
gettingSizeLabel.text = text;
gettingSizeLabel.numberOfLines = 0;
CGSize maximumLabelSize = CGSizeMake(240, 9999); // this width will be as per your requirement
CGSize expectedSize = [gettingSizeLabel sizeThatFits:maximumLabelSize];
return expectedSize.height;
}
I have tried many and found this to work the best
4) Add some logic in the cell height to make use of this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) { // Set the height for our changing textView
return 30 + [self getHeightOfBio:_textView.text];
}
return 44;
}
Obvious we need a bit more height than our text height so I added an extra cushion amount which can be experimented with.
5) Refresh the view each time a character is typed to check if we need to increase the size:
- (void)textViewDidChange:(UITextView *)textView {
if ([self getHeightOfText:textView.text] != _textHeight) {
_textHeight = [self getHeightOfText:textView.text];
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
}
In this section we get the height of the text each time the user types.
Then though we use our stored value and compare the current value to the stored value. Obviously if they are the same then there is no point in refreshing the view. If they are different we update the value and then refresh our table.
This bit I found a good answer on stackOverflow showing how we can refresh only the heights of the table instead of the cell itself. Why refresh the cell when we don't need to? This means that once this is called the cell height is updated and it increases nicely.
Anyway I found this worked really nicely and was simple enough that it can be put together or have different parts taken and put into other peoples pieces of code.
Props to the accepted answer which was pillaged for various pieces along the way but I also hope that this answer helps some people who are having the same difficulties that I had.
Finally I got it working. The main problem is how to get cell's contentView
correct width. Hardcoded width does not work for all cases since it may vary accordingly plain/grouped table style, added accessories, or landscape/portrait layout. The only way to get 100% correct width is to ask it from cell object. So I create cell right in heightForRowAtIndexPath
and store it in cache, then this cached cell will be returned by cellForRowAtIndexPath
method.
Another problem is how to force cell to layout its subviews before it is used. It can be done if we temporary add cell to the tableView
and update cell's frame with tabelView
's width. After that all subviews will be layouted in the right way. Here is how I got it working in my TableKit library.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With