Expand UITextView and UITableView When UITextView Text Expands Out of Line 1

I have a UITableView with two UITextViews next to each other inside each of the cells. I want the UITableViewCell and UITextView to increase in height, so the user does not need to scroll in the UITextView. Here is what I tried:

In the TableViewController class:

self.tableView.estimatedRowHeight = 44 self.tableView.rowHeight = UITableViewAutomaticDimension 

In the TableViewCell class (got it from here ):

 func textViewDidChange(textView: UITextView) { var frame : CGRect = textView.frame frame.size.height = textView.contentSize.height textView.frame = frame } 

When the user enters beyond the specified width of the UITextView, the UITableView increases the height from 44 to 100, and the UITextView does not increase in height. I have restrictions set so that the height of the UITextView is equal to the height of the UITableViewCell.

Any ideas why this is happening, and how to dynamically change the heights of a UITextView and UITableView dynamically?

+3
source share
2 answers

My answer is based on what we definitely use when creating our social application Impether , since you asked me on Twitter that you used the application and you saw the UITextView extension there.

First of all, we have our own UITableViewCell class containing a UITextView that will be expanded (this class has a corresponding xib file as well, which you can create yourself):

 class MultiLineTextInputTableViewCell: UITableViewCell { //our cell has also a title, but you //can get rid of it @IBOutlet weak var titleLabel: UILabel! //UITextView we want to expand @IBOutlet weak var textView: UITextView! override init(style: UITableViewCellStyle, reuseIdentifier: String!) { super.init(style: style, reuseIdentifier: reuseIdentifier) } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } /// Custom setter so we can initialize the height of the text view var textString: String { get { return textView?.text ?? "" } set { if let textView = textView { textView.text = newValue textView.delegate?.textViewDidChange?(textView) } } } override func awakeFromNib() { super.awakeFromNib() // Disable scrolling inside the text view so we enlarge to fitted size textView?.scrollEnabled = false } override func setSelected(selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) if selected { textView?.becomeFirstResponder() } else { textView?.resignFirstResponder() } } } 

Having defined a custom cell, you can use it in a UITableViewController class like this:

 class YourTableViewController: UITableViewController { //in case where you want to have //multiple expanding text views var activeTextView: UITextView? override func viewDidLoad() { super.viewDidLoad() //registering nib for a cell to reuse tableView.registerNib( UINib(nibName: "MultiLineTextInputTableViewCell", bundle: nil), forCellReuseIdentifier: "MultiLineTextInputTableViewCell") } override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) //hide keyboard when view controller disappeared if let textView = activeTextView { textView.resignFirstResponder() } } // MARK: - Table view data source override func numberOfSectionsInTableView(tableView: UITableView) -> Int { //put your value here return 1 } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { //put your value here return 2 } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let row = indexPath.row let cell = tableView.dequeueReusableCellWithIdentifier( "MultiLineTextInputTableViewCell", forIndexPath: indexPath) as! MultiLineTextInputTableViewCell let titleText = "Title label for your cell" let textValue = "Text value you want for your text view" cell.titleLabel.text = titleText cell.textView.text = textValue //store row of a cell as a tag, so you can know //which row to reload when the text view is expanded cell.textView.tag = row cell.textView.delegate = self return cell } override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { //standard row height return 44.0 } override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return UITableViewAutomaticDimension } // Override to support conditional editing of the table view. override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { // Return false if you do not want the specified item to be editable. return true } } //extension containing method responsible for expanding text view extension YourTableViewController: UITextViewDelegate { func textViewDidEndEditing(textView: UITextView) { let value = textView.text //you can do something here when editing is ended } func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool { //if you hit "Enter" you resign first responder //and don't put this character into text view text if text == "\n" { textView.resignFirstResponder() return false } return true } func textViewDidBeginEditing(textView: UITextView) { activeTextView = textView } //this actually resize a text view func textViewDidChange(textView: UITextView) { let size = textView.bounds.size let newSize = textView.sizeThatFits(CGSize(width: size.width, height: CGFloat.max)) // Resize the cell only when cell size is changed if size.height != newSize.height { UIView.setAnimationsEnabled(false) tableView?.beginUpdates() tableView?.endUpdates() UIView.setAnimationsEnabled(true) let thisIndexPath = NSIndexPath(forRow: textView.tag, inSection: 0) tableView?.scrollToRowAtIndexPath(thisIndexPath, atScrollPosition: .Bottom, animated: false) } } } 
+8
source

First, make sure that the automatic layout restriction does not conflict with the frame you set. (If everything is ok, but still does not work), try changing the frame to bounds . The presentation frame (CGRect) represents the position of its rectangle in the supervisor's coordinate system. Using frame can sometimes cause a strange problem in my experience.

 func textViewDidChange(textView: UITextView) { var frame : CGRect = textView.bounds frame.size.height = textView.contentSize.height textView.bounds = frame } 
+1
source

All Articles