I have an UITableViewController that contains a custom cell. Each cell was created using a nib and contains a single non-scrollable UITextView. I have added constraints insi
Inspired by the two previous answers, I found a way to solve my problem. I think the fact that I had a UITextView was causing some troubles with autoLayout. I added the following two functions to my original code.
- (CGFloat)textViewHeightForAttributedText: (NSAttributedString*)text andWidth: (CGFloat)width {
UITextView *calculationView = [[UITextView alloc] init];
[calculationView setAttributedText:text];
CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];
return size.height;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UIFont *font = [UIFont systemFontOfSize:14.0];
NSDictionary *attrsDictionary = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:self.sampleStrings[indexPath.row] attributes:attrsDictionary];
return [self textViewHeightForAttributedText:attrString andWidth:CGRectGetWidth(self.tableView.bounds)-31]+20;
}
where in the last line 31
is the sum of my constraints to the left and right sides of the cell and 20
is just some arbitrary slack.
I found this solution while reading this this very interesting answer.
Tested on iOS 12
I really tried a lot of solutions and finally found a good one here
This works with animation and looks beautiful. The trick was the DispatchQueue.async
block.
I also used TPKeyboardAvoidingTableView to make sure the keyboard doesn't overlap anything.
func textViewDidChange(_ textView: UITextView) {
// Animated height update
DispatchQueue.main.async {
self.tableView?.beginUpdates()
self.tableView?.endUpdates()
}
}
UPDATE
I got strange jumping issues because of TPKeyboardAvoidingTableView
. Especially when I scrolled to the bottom and then a UITextView
got active.
So I replaced TPKeyboardAvoidingTableView
by native UITableView
and handle the insets myself. The table view is does the scrolling natively.
Check out the Objective C solution I have provided in the following link below. Simple to implement, clean, and no need for auto layout. No constraints needed. Tested in iOS10 and iOS11.
Resize and move UITableViewCell smoothly without dismissing keyboard
The solution almost everyone suggested is the way to go, I will add only a minor improvement. As a recap:
Simply set the estimated height, I do it via storyboard:
Make sure you have the constraints for the UITextView correctly set within the cell.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
I simply call:
cell.myTextView.sizeToFit()
Using Swift 2.2 (earlier versions would likely work too), if you set the TableView to use auto dimensions (assuming you're working in a subclassed UITableViewController
, like so:
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 50 // or something
You just need to implement the delegate in this file, UITextViewDelegate
, and add the below function, and it should work. Just remember to set your textView's delegate to self
(so, perhaps after you've dequeued the cell, cell.myTextView.delegate = self
)
func textViewDidChange(textView: UITextView) {
self.tableView.beginUpdates()
textView.frame = CGRectMake(textView.frame.minX, textView.frame.minY, textView.frame.width, textView.contentSize.height + 40)
self.tableView.endUpdates()
}
Thanks to "Jose Tomy Joseph" for inspiring (enabling, really) this answer.
Previously beginUpdates
/endUpdates
were the advertised solution.
Since iOS 11, performBatchUpdates
is what has been recommended source.
Calling performBatchUpdates
after making a change to a cell's content works for me.