20

I'm using the following code to have the UITableViewCell have a dynamic height:

tableView.estimatedRowHeight = 155
tableView.rowHeight = UITableViewAutomaticDimension

And this code to have the UITextView change it's height based on the content.

extension NewUserTweetTableVC: UITextViewDelegate {

    func textViewDidChange(textView: UITextView) {
        let fixedWidth = textView.frame.size.width
        textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max))
        let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max))
        var newFrame = textView.frame
        newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
        textView.frame = newFrame    
    }
}

Once I change the text of the UITextView during runtime, the height of the UITextView changes, but the height of the UITableViewCell does not. How can I change that? Help is very appreciated.

enter image description here enter image description here

David Seek
  • 16,783
  • 19
  • 105
  • 136
  • Check this Q :- http://stackoverflow.com/questions/37014919/expand-uitextview-and-uitableview-when-uitextviews-text-extends-beyond-1-line – Rahul Mayani Sep 14 '16 at 08:09

7 Answers7

37

Get programmatically height of textview...

let textView = UITextView()//your Text view
let sizeThatShouldFitTheContent = textView.sizeThatFits(textView.frame.size)
let height = sizeThatShouldFitTheContent.height

OR try this demo...

Self-sizing UITextView in a UITableView

https://www.damienpontifex.com/posts/self-sizing-uitableviewcell-with-uitextview-in-ios8/

rs7
  • 1,618
  • 1
  • 8
  • 16
Rahul Mayani
  • 3,761
  • 4
  • 25
  • 40
  • 3
    even tho stackoverflow dont want people just to post links, because links can go down, this actually helped me. – David Seek Sep 14 '16 at 10:12
  • 9
    and now the link is down :( – devinross Apr 23 '18 at 23:12
  • The mentioned link is down – SARATH SASI Nov 12 '18 at 09:19
  • This link is back online, but I think it would be worth summarizing its contents here, because it did work brilliantly. Most other answers listed here are only a piece in the puzzle. In short, disable scrolling of the text view, make sure you can initialize your value on the text view so it will call textViewDidChange, then calculate if the height has changed, and if so, call begin/endUpdates on the tableView, while wrapping/sandwiching those calls in UIView.setAnimationsEnabled(false/true) – horseshoe7 Jan 23 '20 at 08:54
  • 1
    This is really helpful... Thanks @rahul and rs7. – Hari Narayanan Apr 15 '20 at 19:12
  • Thank. Your git is old code. but it's very good. – Ten Jun 21 '21 at 03:45
11

If you are using UITableViewAutomaticDimension then you must set serial constraints from top to bottom. Without autolayout or proper constraints UITableViewAutomaticDimension won't work. So you can manage this thing something like: set top,bottom,leading,trailing and fixed height constraints to your textview. then take outlet of fixed height constraint and increase it's constant instead changing or setting frame of textview and everythng will work I think!

user1898712
  • 368
  • 6
  • 18
Ketan Parmar
  • 27,092
  • 9
  • 50
  • 75
11

Step 1, Disable Scrolling of TextView
Step 2, Add Top, Left, Right and bottom constraint
Step 3, Set Delegate to textView
Step 4, Implement below UITextViewDelegate Method

- (void)textViewDidChange:(UITextView *)textView {
[UIView setAnimationsEnabled:false];
[textView sizeToFit];
[self.tableView beginUpdates];
[self.tableView endUpdates];
[UIView setAnimationsEnabled:true];}
iOS Lifee
  • 2,091
  • 23
  • 32
5

I am improving Lion's answer.

If you are using UITableViewAutomaticDimension then you must set serial constraints from top to bottom. Without autolayout or proper constraints UITableViewAutomaticDimension won't work. So you can manage this thing something like: set top,bottom,leading,trailing and fixed height constraints to your textview. Disable the scrolling feature of UITextview and you are done. You are not required to fixed height constraint.

Amrit Sidhu
  • 1,870
  • 1
  • 18
  • 32
5

Update code in Swift 4.2
Credit: http://www.swiftdevcenter.com/the-dynamic-height-of-uitextview-inside-uitableviewcell-swift/
Create a Custom cell with name GrowingCell, add UITextView in the cell and create an Outlet of this. Register this cell in UITableView in your ViewController class. Your ViewController:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let nib = UINib(nibName: "GrowingCell", bundle: nil)
        self.tableView.register(nib, forCellReuseIdentifier: "GrowingCell")
        self.tableView.tableFooterView = UIView()
        self.tableView.dataSource = self
    }
}

extension ViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "GrowingCell", for: indexPath) as! GrowingCell
        cell.cellDelegate = self
        return cell
    }

}

extension ViewController: GrowingCellProtocol {
    // Update height of UITextView based on string height
    func updateHeightOfRow(_ cell: GrowingCell, _ textView: UITextView) {
        let size = textView.bounds.size
        let newSize = tableView.sizeThatFits(CGSize(width: size.width,
                                                        height: CGFloat.greatestFiniteMagnitude))
        if size.height != newSize.height {
            UIView.setAnimationsEnabled(false)
            tableView?.beginUpdates()
            tableView?.endUpdates()
            UIView.setAnimationsEnabled(true)
            // Scoll up your textview if required
            if let thisIndexPath = tableView.indexPath(for: cell) {
                tableView.scrollToRow(at: thisIndexPath, at: .bottom, animated: false)
            }
        }
    }
}

Now move to your Custom GrowingCell cell and add below code:

import UIKit

protocol GrowingCellProtocol: class {
    func updateHeightOfRow(_ cell: GrowingCell, _ textView: UITextView)
}

class GrowingCell: UITableViewCell {

    weak var cellDelegate: GrowingCellProtocol?
    @IBOutlet weak var textView: UITextView!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        textView.delegate = self
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        // Configure the view for the selected state
    }
}

extension GrowingCell: UITextViewDelegate {

    func textViewDidChange(_ textView: UITextView) {
        if let deletate = cellDelegate {
            deletate.updateHeightOfRow(self, textView)
        }
    }
}

For more detail: visit this full demo

Ashish Chauhan
  • 1,316
  • 15
  • 22
3

You need to disable the scrolling of the text view to make the tableViewCell autoresize according to the content size of the textView.

J. Doe
  • 12,159
  • 9
  • 60
  • 114
-1

Not sure it can help you or not, but I custom an UITextView that fitting the content height as its height.

This is the TextView from your UITableViewCell:

final class ContentFittingTextView: UITextView {
    override var contentSize: CGSize {
        didSet {
            invalidateIntrinsicContentSize()
        }
    }

    override var intrinsicContentSize: CGSize {
        self.layoutIfNeeded()
        return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
    }
}

and from your UITableView:

tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 44
Tai Le
  • 8,530
  • 5
  • 41
  • 34