如何在自定义单元格中同步选择文本视图的事件?
Posted
技术标签:
【中文标题】如何在自定义单元格中同步选择文本视图的事件?【英文标题】:How to synchronise events on the selection of a textview in a custom cell? 【发布时间】:2019-06-05 18:45:36 【问题描述】:我在自定义单元格中有一个 textView,当我开始编辑时,我希望按钮出现在单元格中。为此,我创建了一个变量“selectedIndexPathRow”,在“textViewDidBeginEditing”函数中将 textView 的 indexPath.row 分配给该变量。
func textViewDidBeginEditing(_ textView: UITextView)
let touchPosition:CGPoint = textView.convert(CGPoint.zero, to: self.createStoryTableView)
let indexPath = self.createStoryTableView.indexPathForRow(at: touchPosition)
self.selectedIndexPathRow = indexPath?.row ?? 0
.....
之后,在我的 cellForRowAt 中,我可以根据 indexPathRow 是否与变量匹配来显示或隐藏按钮。如下:
if indexPath.row == selectedIndexPathRow
cell.inputTextView.isEditable = true
cell.createBtnStack.isHidden = false
else
cell.createBtnStack.isHidden = true
问题是按钮仅在编辑完成后出现(在按 enter 或单击 textView 外部时),而不是在编辑开始时(或单击 textView 时)。
为了解决这个问题,我尝试了以下方法:
将 tableview.reloaddata() 放入“didBeginEditing”。这会同步生成按钮,但会导致 textview 冻结。
使用'textViewShouldBeginEditing'函数如下尝试预先设置selectIndexPathRow变量:
func textViewShouldBeginEditing(_ textView: UITextView) -> 布尔
让 touchPosition:CGPoint = textView.convert(CGPoint.zero, 到: self.createStoryTableView)
让 indexPath = self.createStoryTableView.indexPathForRow(at: touchPosition)
self.selectedIndexPathRow = indexPath?.row ?? 0
返回真
但是这样做的结果并不一致-有时可以在单击后直接编辑文本视图而没有显示任何按钮,有时会显示按钮但您必须再次单击才能编辑文本视图。
如果您对如何解决此问题有任何建议,请告诉我。
【问题讨论】:
【参考方案1】:通过将单元格设置为其文本字段的委托,让单元格管理自己的编辑状态。这是一个示例游乐场:
import UIKit
import PlaygroundSupport
class Cell: UITableViewCell
let textView = UITextView()
let button = UIButton()
lazy var stackView: UIStackView =
let stack = UIStackView(arrangedSubviews: [textView, button])
stack.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(stack)
NSLayoutConstraint.activate([
stack.heightAnchor.constraint(equalToConstant: 120),
stack.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 12),
stack.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -12),
stack.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 12),
stack.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -12)
])
button.setTitle("Button", for: .normal)
button.addTarget(self, action: #selector(tapButton), for: .touchUpInside)
textView.delegate = self
return stack
()
func configure()
contentView.backgroundColor = .gray
_ = stackView
button.isHidden = !textView.isFirstResponder
@objc private func tapButton()
contentView.endEditing(true)
extension Cell: UITextViewDelegate
func textViewDidBeginEditing(_ textView: UITextView)
button.isHidden = false
func textViewDidEndEditing(_ textView: UITextView)
button.isHidden = true
class V: UITableViewController
override func viewDidLoad()
super.viewDidLoad()
tableView.register(Cell.self, forCellReuseIdentifier: String(describing: Cell.self))
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return 1
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: Cell.self), for: indexPath)
(cell as? Cell)?.configure()
return cell
PlaygroundPage.current.liveView = V()
【讨论】:
感谢乔希的回复。将单元格设置为 textView 的委托是一个好主意。唯一的问题是我仍然需要访问 tableView 才能在 textViewDidBeginEditing 中执行其他事件,例如就像滚动到 selectedRow 一样。除非我弄错了,否则我无法从单元格访问 tableView。 通过沿着响应者链向上走,很容易从它的任何孩子那里获得任何父 UIResponder(包括一个 tableview)。请在此处查看我的答案:***.com/questions/55578880/…以上是关于如何在自定义单元格中同步选择文本视图的事件?的主要内容,如果未能解决你的问题,请参考以下文章
自定义表格视图单元格中的 UITextField。点击单元格/文本字段时显示选择器视图
如何在自定义单元格中点击以编程方式添加的 UiImageViews 推送新视图
如何在自定义滑动(而不是滑动删除)单元格(滑动到邮件/短信)中点击一个单元格时删除在其他 TableView 单元格中添加的子视图