【问题标题】:Strange behavior of UITextView in UITableViewCellUITableViewCell 中 UITextView 的奇怪行为
【发布时间】:2016-01-25 16:04:00
【问题描述】:

我有一个包含几个堆栈视图的单元格,底部堆栈视图包含一个 textView 和一个自定义分隔符。

我想创建一个选项,当用户点击单元格时,它会显示点击文本视图的整个文本,因此该单元格中的最大行数为 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 高度有一个奇怪的行为。当第一个单元格被扩展时,我向下滚动,最后一个单元格也被扩展,不应该。

【问题讨论】:

  • 你的 heightForRowAtIndexPath 是什么样的?
  • 因为tableView.estimatedRowHeight = 160 tableView.rowHeight = UITableViewAutomaticDimension我没用过
  • 在使用estimatedRowHeight + UITableViewAutomaticDimension时不应该有heightForRowAtIndexPath
  • 从我知道的另一个项目中,如果在 cellForRow 中的 if-else 语句中设置了某些内容,并且在 else 分支中没有取消设置,它也可能有奇怪的行为,但我不这么认为是我的情况,因为我已经覆盖了 cellForRow 中的所有 if else 分支,还是没有?

标签: ios swift uitableview uitextview


【解决方案1】:

在选择时动态调整 UITableViewCell 的大小

使用单个选择索引是危险的事情。您不仅可能会错过didSelectRowAtIndexPath 中的极端情况,而且它不可能适用于多项选择。
您应该将单元格扩展/压缩通知分成 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)
}

选择被 selectRowAtIndexPath 破坏

这可以防止didDeselectRowAtIndexPath 被调用。 一种解决方法是缓存整个选择,而不是单个索引,并在重新加载后恢复此类选择。

完整代码

注意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 上查找此解决方案,在Swift Recipes 上查找更多详细信息。

【讨论】:

  • 好的,假设我按照您的建议将扩展/收缩分成两个不同的块(didSelectdidDeselect)。我现在的问题是,cellForRow 怎么样,我的 if 语句应该是什么来为我的 textView 选择正确的最大行数,因为正如你所说我不需要跟踪 selectedIndexPath?我真的没有看到你的目标,你能给我一个提示吗?
  • 创建项目,添加演示和链接。
【解决方案2】:

我没有找到答案,为什么会出现 textView 和单元格高度的奇怪行为,但我有解决问题的方法。

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

所以我从 StackView 解开 textView 和底部分隔符,用 Label 替换 TextView 并设置 autolayaut 约束。现在它工作正常,没有奇怪的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-19
    • 2014-05-28
    • 1970-01-01
    • 2014-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多