具有多行输入字段的 UITableViewCell?
Posted
技术标签:
【中文标题】具有多行输入字段的 UITableViewCell?【英文标题】:UITableViewCell with multiline input field? 【发布时间】:2016-09-13 08:56:48 【问题描述】:我想创建一个带有多行输入字段(文本视图)的 uitableview 单元格。当用户输入文本时,文本视图或单元格的高度应自动增加。
【问题讨论】:
我明白你在问什么:你想要一个 UITableView ,用户可以在其中编辑行中的文本。然后,您希望文本字段根据需要实时扩展以容纳文本? 是的,这正是我想要的。 【参考方案1】:您好:这一直困扰着我一整天,但我只是把一些我认为已经破解的东西放在一起。我假设您知道如何将基本的 tableView 放在一起。
您需要为每一行添加一个 UITextView,并且至关重要的是,让您的 tableViewController 成为每个 UITextView 的委托。除了每一行的字符串值数组外,您还需要每行都有一个高度数组(CGFloats)。另一个关键方面是为每个 textView 分配一个与单元格的 indexPath.row 相等的数字标签,这使我们能够跟踪我们正在处理的 textView。这将作为一个相同值的数组开始,但想法是当文本变得对于现有框架而言太大时,您可以根据需要更新此数组,如下所示。
然后我实现了以下两个委托函数以及一个定制函数,以根据需要更新布局:
func updateLayout(forTextView: UITextView) -> Void
guard forTextView.tag < self.data.count else return // Make sure we're not going to try and access a value that does not exist
self.data[forTextView.tag] = forTextView.text // Update our data array to reflect the new string value for the cell's text view
let newHeight : CGFloat = forTextView.frame.height // The new cell height is based on the height of the text view
let oldHeight : CGFloat = self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: forTextView.tag, inSection: 0))!.frame.height // Retrieving the existing height of the cell
self.heights[forTextView.tag] = newHeight + 2 // Set the new value in the heights array with a 1 point buffer
// Now animate to ease the transition
UIView.animateWithDuration(0.25)
for cell in self.tableView.visibleCells
if let indexPath = self.tableView.indexPathForCell(cell)
// We only need to update the edited cell and all cells below it
if indexPath.row > forTextView.tag
cell.frame = CGRect(origin: CGPointMake(cell.frame.origin.x, cell.frame.origin.y + forTextView.frame.height + 2 - oldHeight), size: CGSizeMake(cell.frame.width, self.heights[indexPath.row]))
else if indexPath.row == forTextView.tag
cell.frame = CGRect(origin: cell.frame.origin, size: CGSizeMake(cell.frame.width, self.heights[indexPath.row]))
func textViewDidEndEditing(textView: UITextView)
// Update the cell and exit
self.updateLayout(textView)
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool
// More complicated: we need to update the frame but also maintain focus in this textView as the user has not finished editing yet
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(CGPointMake(0, 5), animated: false)
self.updateLayout(textView)
// This code puts an active cursor back at the end of the textView's text
textView.selectedRange = NSRange(location: textView.text.characters.count, length: 0)
textView.becomeFirstResponder()
return true
棘手的部分是更新 tableView 的布局,同时将光标的焦点保持在正在积极编辑的字段中。
我对在文本字段需要扩展时提供平滑过渡的结果感到非常满意。
我不想把完整的代码发给你,因为最好自己把这些东西放在一起;但是,如果您真的被卡住了,请给我留言,我会发送给您。万事如意!
【讨论】:
【参考方案2】:我找到了比上述答案更简单的方法。使用 UITextView 创建一个自定义单元格,如下所示:
private lazy var valueTextField: UITextView =
let textField = UITextView()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.layer.borderWidth = 0.8
textField.layer.borderColor = UIColor(displayP3Red: 204/255.0, green: 204/255.0, blue: 204255.0, alpha: 1).cgColor
textField.layer.cornerRadius = 5
textField.textColor = .black
textField.isUserInteractionEnabled = true
textField.isEditable = true
textField.isScrollEnabled = false
textField.textContainer.lineBreakMode = .byWordWrapping
textField.delegate = self
return textField
()
根据需要更改属性。
现在在视图中添加这个 UiTextView。比如:
view.addSubView(valueTextField)
然后创建类似如下的回调:
var textChanged: ((String) -> Void)?
func textViewDidChange(_ textView: UITextView)
textChanged?(textView.text)
func textChanged(action: @escaping (String) -> Void)
textChanged = action
然后在 TableViewController 中的 cellForRowAt 内部实现回调并使用 begin 和 end 更新调用刷新 tableview:
(cell as! CustomCell).textChanged [weak tableView] (newText: String) in
DispatchQueue.main.async
tableView?.beginUpdates()
tableView?.endUpdates()
就是这样。您的 textView 应该按预期工作。
【讨论】:
以上是关于具有多行输入字段的 UITableViewCell?的主要内容,如果未能解决你的问题,请参考以下文章
iOS Autolayout 2 多行 UILabel 在 UITableViewCell 中具有额外的填充
uitableviewcell 具有动态高度或减小字体大小以将多行放入一个单元格
UITableViewCell 中的多行 UILabel 在 iOS8 中使用 autoLayout 给出错误的高度