UITextView在UITableViewCell中的奇怪行为

我有一个包含几个stackviews的单元格,底部的stackView包含一个textView和一个自定义分隔符。

我的手机

我想创build一个选项,当用户点击单元格时,它会显示点击文本视图的全部文本,因此该单元格中的最大行数为0,其他单元格为3。

我用这个教程http://www.roostersoftstudios.com/2011/04/14/iphone-uitableview-with-animated-expanding-cells/我修改了一下,我的代码:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier(iden_tableViewCell4) as! TableViewCell4 if let selectedCellIP = selectedIndexPath { if indexPath == selectedCellIP { cell.textTextVIew.textContainer.maximumNumberOfLines = 0 } else { cell.textTextVIew.textContainer.maximumNumberOfLines = textVIewMaxNumberOfLines } } else { cell.textTextVIew.textContainer.maximumNumberOfLines = textVIewMaxNumberOfLines } return cell } func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { tableView.deselectRowAtIndexPath(indexPath, animated: true) //The user is selecting the cell which is currently expanded //we want to minimize it back if selectedIndexPath == indexPath { selectedIndexPath = nil tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) return } //First we check if a cell is already expanded. //If it is we want to minimize make sure it is reloaded to minimize it back if let selIndexPath = selectedIndexPath { let previousPath = selIndexPath selectedIndexPath = indexPath tableView.reloadRowsAtIndexPaths([previousPath], withRowAnimation: .Fade) } //Finally set the selected index to the new selection and reload it to expand selectedIndexPath = indexPath tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) } 

在我的viewDidLoad我设置tableView.estimatedRowHeight = 160 tableView.rowHeight = UITableViewAutomaticDimension

扩展和收缩工作得很好,但其他单元格的textView高度有一个奇怪的行为。 当第一个单元格被扩展时,我向下滚动,最后一个单元格也被扩展了,不应该是。 在这里输入图像说明

在select时dynamic调整UITableViewCell的大小

玩个人select指标是危险的事情。 您不仅可能会错过didSelectRowAtIndexPathangular落情况条件,它不可能用于多个select。
您应该将单元格扩展/压缩通知拆分为2个不同的块(不需要跟踪selectedIndexPath ,更健壮的代码)

扩大

 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { self.reloadRowsAtIndexPaths(tableView, indexPath:indexPath) } 

合同

 override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { self.reloadRowsAtIndexPaths(tableView, indexPath:indexPath) } 

select被selectRowAtIndexPath销毁

这可以防止调用didDeselectRowAtIndexPath 。 解决方法是caching整个select,而不是单个索引,并在重新加载后恢复这种select。

完整的代码

注意何时以及如何保持cacheSelectedRows 。 这使用一个普通的UITableViewCell 。 所有它需要的是一个reuseIdentifier

 class TableViewController: UITableViewController { var cacheSelectedRows:[IndexPath]? = nil override func viewDidLoad() { super.viewDidLoad() tableView.estimatedRowHeight = 160 tableView.rowHeight = UITableViewAutomaticDimension } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 8 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) if let textLabel = cell.textLabel { textLabel.backgroundColor = UIColor.clear textLabel.numberOfLines = 1 if let cacheSelectedRows = cacheSelectedRows { textLabel.numberOfLines = (cacheSelectedRows.contains(indexPath)) ? 0 : 1 } textLabel.text = "\(1 + indexPath.row), Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." } return cell } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { self.reloadRowsAtIndexPaths(tableView, indexPath:indexPath) } override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { self.reloadRowsAtIndexPaths(tableView, indexPath:indexPath) } func reloadRowsAtIndexPaths(_ tableView: UITableView, indexPath: IndexPath) { cacheSelectedRows = tableView.indexPathsForSelectedRows tableView.reloadRows(at: [indexPath], with: .fade) // Restore selection if let cacheSelectedRows = cacheSelectedRows { for path in cacheSelectedRows { self.tableView.selectRow(at: path, animated: false, scrollPosition: .none) } } } } 

演示

动画演示


►在GitHub上find这个解决scheme和Swift Recipes的更多细节。

我没有find答案,为什么textView和单元格高度的奇怪行为正在发生,但我有我的问题的解决scheme。

所以它看起来像tableView.estimatedRowHeight = 160tableView.rowHeight = UITableViewAutomaticDimension不尊重textView的所有单元格的最大行数。 cellForRow工作正常,它设置的限制,但行高有时扩大,有时收缩。

所以我解包了textView和StackView的底部分隔符,用Labelreplace了TextView并设置了自动布局约束。 现在它工作正常,没有奇怪的行为。