Resizing UITextView in custom UITableViewCell

I have a custom UITableViewCell and I’m trying to resize the UITextView inside it based on the content size. I’m on iOS7 and using Autolayout.

I’ve tried using the following:

  • MPMoviePlayerController switching movies causes white flash
  • Distinguish between an iPhone App crashing and being killed
  • How can I take a screenshot of the iPhone home screen programmatically
  • FCM - Programatically Send Push Notification To User Segments
  • tableView reloadData not working
  • check if control center is used
  • [cell.question setScrollEnabled:YES];
    [cell.question sizeToFit];
    [cell.question setScrollEnabled:NO];
    

    and

    - (CGRect)textViewHeightForAttributedText: (NSAttributedString*)text andWidth: (CGFloat)width
    {
        UITextView *calculationView = [[UITextView alloc] init];
        [calculationView setAttributedText:text];
        CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];
        CGRect finalFrame = CGRectMake(0, 0, width, size.height);
        return finalFrame;
    }
    

    from different SO posts. I’m able to resize the frame. But the issue is I’m not able to see the change visibly. In the sense, when I log it, I can see the change. But the UITextView doesnt resize. I cant find any autolayout dependencies either.

    When I disabled AutoLayout, it seems to work. How do I do this, by enabling AutoLayout?

    Thanks.

    EDIT

    Here’s my UITextView constraints

    Screenshot

    6 Solutions Collect From Internet About “Resizing UITextView in custom UITableViewCell”

    You have to do this calculation in

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
    

    method and also resize the cell height accordingly.

    If you got it, it’s okay. Or If you need the code sample, just ask again.
    I think you got it !

    Updated

        - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
                UITextView *tempTV = [[UITextView alloc] init];
                [tempTV setText:@"your text"];
                CGFloat width = self.tableView.frame.size.width - TEXT_ORIGIN_X - TEXT_END_X;
                CGSize size = [tempTV sizeThatFits:CGSizeMake(width, MAX_HEIGHT)];
                return (TEXT_ORIGIN_Y + size.height + TEXT_BOTTOM_SPACE);
        }
    

    You may forget implement the heightForRowAtIndexPath method of TableView’s delegete;

    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        CGFloat  yourTextViewsHeight = ... calculate it here
        return yourTextViewsHeight;
    }
    

    I think you might have too many constraints for the text view. I can’t be sure of this because it’s difficult to communicate information about constraints that are built in IB.

    Your text view only needs two constraints, one for each axis, in order to be fully constrained. One constraint should position the text view horizontally, the other vertically. The text view’s intrinsic content size will be used by the Auto Layout system to automatically generate size constraints for the text view.

    I think some of the constraints you have in place now are preventing resizing of the text view. This happens because, by default, constraints you create yourself are required (priority 1000). The automatically-generated sizing constraints, on the other hand, have a lower priority and will be overruled by any conflicting constraints that are required.

    Note: just because the text view only needs two constraints to be fully constrained doesn’t mean that you can’t have more constraints. A table cell with 4 labels, 3 image views, and 1 text view is a complex layout, so you will most likely constrain other UI objects relative to the text view, rather than the superview.

    I had the same issue but in a different situation. I have UItableview with two custom cells.
    
    First Custom cell - self expanding textview. (like email type message box)
    Second Custom Cell -  Static image. 
    
    Have a  look at my code. You will get an insight to automatic resizing of cells.
    
    //  ViewController.swift
    //  ListWrap
    
    import UIKit
    
    class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate, UITextViewDelegate {
    
        @IBOutlet var listWrapTableView: UITableView!
    
        //CustomCells
        var CellIdentifier: String = "ListWrapTableViewCellID"
        var tapGesture: UITapGestureRecognizer!
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
        override func viewWillAppear(animated: Bool) {
            //Adding Tap Gesture To Table
            tapGesture = UITapGestureRecognizer(target: self, action: "tapRecognized:")
            self.listWrapTableView.addGestureRecognizer(tapGesture)
            tapGesture.cancelsTouchesInView = false
            tapGesture.enabled =  true
        }
        func tapRecognized(recognizer: UITapGestureRecognizer){
            self.listWrapTableView.endEditing(true)
        }
        func textViewDidBeginEditing(textView: UITextView) {
            if (CellIdentifier == "ListWrapTableViewCellID")
            {
                tapGesture.enabled =  true
            }
            else
            {
                tapGesture.enabled =  false
            }
        }
        // MARK: - Table view data source
        func numberOfSectionsInTableView(tableView: UITableView) -> Int {
            return 1
        }
        func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
        {
            self.listWrapTableView.rowHeight = UITableViewAutomaticDimension
            return self.listWrapTableView.rowHeight
        }
        func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
            return UITableViewAutomaticDimension
        }
        func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return 2
        }
        func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    
            if (indexPath.row == 0)
            {
                let surveyCell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier)! as! ListWrapTableViewCell
                return surveyCell
            }
            else if (indexPath.row == 1)
            {
                let reportsCell = tableView.dequeueReusableCellWithIdentifier("ListWrapSecondTableViewCellID")! as! ListWrapSecondTableViewCell
                return reportsCell
            }
            else
            {
                let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "")
                return cell
            }
        }
        func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
        {
        }
    }
    
    
    
    The first Custom cell:
    
    //  ListWrapTableViewCell.swift
    //  ListWrap
    
    import UIKit
    
    class ListWrapTableViewCell: UITableViewCell{
    
        @IBOutlet var listWrapTextView: 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 initialise the height of the text view
        var textString: String {
            get {
                return listWrapTextView.text
            }
            set {
                listWrapTextView.text = newValue
                textViewDidChange(listWrapTextView)
            }
        }
    
        override func awakeFromNib() {
            super.awakeFromNib()
            listWrapTextView.scrollEnabled = false
            listWrapTextView.delegate = self
        }
        override func setSelected(selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)
            if selected {
                listWrapTextView.becomeFirstResponder()
            } else {
                listWrapTextView.resignFirstResponder()
            }
        }
    }
    extension ListWrapTableViewCell: UITextViewDelegate {
        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's size is changed
            if size.height != newSize.height {
                UIView.setAnimationsEnabled(false)
                tableView?.beginUpdates()
                tableView?.endUpdates()
                UIView.setAnimationsEnabled(true)
    
                if let thisIndexPath = tableView?.indexPathForCell(self) {
                    tableView?.scrollToRowAtIndexPath(thisIndexPath, atScrollPosition: .Bottom, animated: false)
                }
            }
        }
    }
    extension UITableViewCell {
        /// Search up the view hierarchy of the table view cell to find the containing table view
        var tableView: UITableView? {
            get {
                var table: UIView? = superview
                while !(table is UITableView) && table != nil {
                    table = table?.superview
                }
    
                return table as? UITableView
            }
        }
    }
    
    The second custom cell: 
    
    //  ListWrapSecondTableViewCell.swift
    //  ListWrap
    
    
    import UIKit
    
    class ListWrapSecondTableViewCell: UITableViewCell {
    
        override func awakeFromNib() {
            super.awakeFromNib()
        }
        override func setSelected(selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)
        }
    
    }
    
    
    attaching storyBoard for further reference.
    

    enter image description here

    Your layout is a bit more complex, but it should not matter if everything is set up properly.

    You do not have to calculate anything (by using sizeThatFits).

    All you have to do is disable UITextView’s scrolling enabled property then on textViewDidChange call tableView.beginUpdates() and tableView.endUpdates(). That doesn’t break the first responder and resizes the table view smoothly.

    For a detailed explanation, check out a post I wrote which also includes a working sample project.

    try this

    set your UITextView outlet like this in your custom UITableViewCell class

    [yourTextView setAutoresizesSubviews:YES];
    yourTextView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    

    hope this will work for you