如何在用户输入时使UITableView单元格动态地改变其高度?

时间:2017-10-04 20:03:02

标签: ios swift uitableview

我目前正在开发一种功能,可以在键入时动态更改UITableView单元格的高度。因此,如果用户键入的项目扩展了单元格的当前最大宽度,则单元格的高度应该增加。我的专业TableViewCell包含一个TextView和一个UILabel,并且还连接到它下面的另一个单元格。因此,在一个TableView中有一个带有两个TableViewCell的TableView。我一直试图尝试解决方法,但到目前为止还没有任何工作。有没有人有任何概念性的想法来完成它?

2 个答案:

答案 0 :(得分:3)

首先将tableView rowHeight设置为UITableViewAutomaticDimension,在表格视图单元格中添加具有top,leading,bottom和trailing约束的UITextView。将textView.isEditable设置为true,将textView.isScrollEnabled设置为false,然后实现textView委托方法textViewDidChange。当文本更改时,您需要报告以查看控制器以更新tableview,一种方法是通过委派。在视图控制器中实施表格视图单元格委托,您可以在其中调用tableView.beginUpdates()tableView.endUpdates()。而已。下面是一个经过测试和运作的例子。

您的视图控制器:

import UIKit
class ViewController: UIViewController, UITableViewDataSource, ExpandingTableViewCellDelegate {

    @IBOutlet weak var tableView: UITableView!
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.dataSource = self
        tableView.register(UINib(nibName: "ExpandingTableViewCell", bundle: nil), forCellReuseIdentifier: "ExpandingTableViewCellIdentifier")
        tableView.rowHeight = UITableViewAutomaticDimension
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

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

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

    // Expanding teable view cell delegate
    func didChangeText(text: String?, cell: ExpandingTableViewCell) {
        tableView.beginUpdates()
        tableView.endUpdates()
    }
}

你的手机:

import UIKit
protocol ExpandingTableViewCellDelegate: class {
    func didChangeText(text: String?, cell: ExpandingTableViewCell)
}

class ExpandingTableViewCell: UITableViewCell, UITextViewDelegate {
    @IBOutlet weak var textView: UITextView!
    weak var delegate: ExpandingTableViewCellDelegate?

    override func awakeFromNib() {
        super.awakeFromNib()

        textView.delegate = self
        textView.isEditable = true
        textView.text = "Start typing: ..."
        textView.isScrollEnabled = false
    }

    func textViewDidChange(_ textView: UITextView) {
        delegate?.didChangeText(text: textView.text, cell: self)
    }
}

示例项目在此处:https://github.com/bavarskis/ExpandingTableViewCell.git

答案 1 :(得分:0)

当您要求概念性地了解正在发生的事情时,您可能希望在我的github页面中查看项目:

https://github.com/mpj-chandler/variableSizeTextTableView

该项目包含一个子类UITableViewController控制器,它也是文本视图的委托。主要功能如下:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    var textFrame : CGRect = textView.frame
    let newHeight : CGFloat = ceil(textView.contentSize.height)
    if newHeight - textFrame.height > 0 {
        textFrame.size.height = ceil(textView.contentSize.height)
        textView.frame = textFrame
        textView.setContentOffset(CGPoint(x: 0, y: 5), animated: false)
        self.updateLayout(textView)
    }

    textView.selectedRange = NSRange(location: textView.text.characters.count, length: 0)
    textView.becomeFirstResponder()
    return true
}


func updateLayout(_ forTextView: UITextView) -> Void {
    guard forTextView.tag < self.data.count else { return }

    self.data[forTextView.tag] = forTextView.text

    let newHeight : CGFloat = forTextView.frame.height
    let oldHeight : CGFloat = self.tableView.cellForRow(at: IndexPath(row: forTextView.tag, section: 0))!.frame.height

    self.heights[forTextView.tag] = newHeight + 2
    UIView.animate(withDuration: 0.25, animations: { 
        for cell in self.tableView.visibleCells {
            if let indexPath = self.tableView.indexPath(for: cell) {
                if (indexPath as NSIndexPath).row > forTextView.tag {
                    cell.frame = CGRect(origin: CGPoint(x: cell.frame.origin.x, y: cell.frame.origin.y + forTextView.frame.height + 2 - oldHeight), size: CGSize(width: cell.frame.width, height: self.heights[(indexPath as NSIndexPath).row]))
                }
                else if (indexPath as NSIndexPath).row == forTextView.tag
                {
                    cell.frame = CGRect(origin: cell.frame.origin, size: CGSize(width: cell.frame.width, height: self.heights[(indexPath as NSIndexPath).row]))
                }
            }
        }
    }) 
}

警告:这是用Swift 2编写的,但对Swift 4的翻译应该是微不足道的。此外,如果您希望表视图可编辑,那么引用带有标签的单元格并不是一个好主意,但希望您能获得要点。

希望它有所帮助。