当UITextView的文本扩展超过1行时展开UITextView和UITableView

我有一个UITableView与两个UITextView并排在每个单元格内。 我希望UITableViewCell和UITextView的高度都增加,以便用户不需要在UITextView中滚动。 这是我试过的:

在TableViewController类中:

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

在TableViewCell类(从这里得到这个):

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

当用户键入超出UITextView的设置宽度时,UITableView将高度从44增加到大约100,并且UITextView的高度不增加。 我有约束设置,使UITextView的高度是相同的UITableViewCell的。

任何想法,为什么发生这种情况, 如何正确地dynamic改变UITextView和UITableView的高度?

我的答案是基于我们的社交应用程序生产的确切用途,因为你在Twitter上问我你使用的应用程序,你看到在那里扩大UITextView。

首先,我们有一个基于UITableViewCell的自定义类,它包含UITextView ,它将被扩展(这个类也有一个对应的xib文件,你可以自己devise):

 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() } } } 

有一个定义的自定义单元格,你可以在基于UITableViewController的类中使用它:

 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's 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) } } } 

首先确保您的自动布局约束不会与您设置的框架发生冲突。 (如果一切正常,但仍然不起作用)然后尝试更改framebounds 。 视图的框架(CGRect)是其矩形在超视图坐标系中的位置。 根据我的经验,使用frame可能会导致奇怪的问题。

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