【问题标题】:How to make a UITableView cell dynamically change its height while user is typing?如何在用户键入时使 UITableView 单元格动态更改其高度?
【发布时间】:2018-03-16 08:14:14
【问题描述】:

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

【问题讨论】:

  • 显示到目前为止您尝试了什么?此外,快速搜索uitextview autosize height 会找到很多解决方案。
  • 嘿,我已经尝试了其中的一些建议,但我的 TableViewCell 仍然没有扩展,因为有人正在输入并达到最大单元格宽度量。通常,网上的解决方案都是将TableView的estimatedRowHeight设置为特定的数字,然后将TableView的rowHeight设置为UITableViewAutomaticDimension[.flexiblehHeight, .flexibleWidth]。但是,我的 TableView 中的单个单元格仍然不想扩展。还有其他想法吗?
  • 您是否已经获得UITextView 以在键入时自动调整大小,只是在普通视图中,而不是在表格视图单元格中?如果没有,那可能是最好的起点。让它工作,然后将其添加到单元格中应该很容易。
  • 顺便说一句...你实际尝试了什么代码?当我在 google 上搜索 uitextview autosize height 时,第 4 个结果是这个链接 - 这是一篇描述如何在表格视图单元格中使用自定大小文本视图的文章,包括一个示例应用程序的链接! (必须从 Swift 2 自动转换为 3,但这没有问题)。所以,这里是直接链接:candycode.io/…

标签: ios swift uitableview


【解决方案1】:

首先将您的 tableView rowHeight 设置为UITableViewAutomaticDimension,在您的表格视图单元格中添加带有顶部、前导、底部和尾部约束的 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

【讨论】:

  • 嘿@Au Ris,感谢您的解决方案,但它似乎对我不起作用。我在 UITextViewDelegate 中为我的专用 TableViewCell 实现了didChangeText 函数,它包含一个 TextView 和一个 UILabel,但是当长度达到单元格的宽度时,当有人键入内容时,单元格的高度仍然不会扩展。你有什么不能更新的想法吗?
  • 获取示例项目并尝试与您的代码进行比较:github.com/bavarskis/ExpandingTableViewCell.git
  • @AuRis - 尝试了示例代码,但它正在调整所有 tableview 单元格的大小,而不仅仅是用户输入的单元格...
  • 该示例仅处理一个单元格。您所体验的很可能是单元重用的效果。您需要将每个单元格的文本存储在视图控制器中,并在 cellForRowAt 委托方法中更新单元格。
【解决方案2】:

当您要求对正在发生的事情进行概念性理解时,您可能希望查看我的 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 应该很简单。此外,如果您希望表格视图可编辑,则使用标签引用单元格不是一个好主意,但希望您能理解要点。

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    • 2014-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多