Strange behavior of UITextView in UITableViewCell

后端 未结 2 567
一整个雨季
一整个雨季 2021-01-23 06:31

I have a cell that contains a few stackviews, bottom stackView contains a textView and a custom separator.

I want to create an option, when user tap on cell, it

相关标签:
2条回答
  • 2021-01-23 06:44

    Dynamically Resize UITableViewCell upon Selection

    Playing with individual selection indexes is dangerous business. Not only are you likely to miss corner case conditions in didSelectRowAtIndexPath, it cannot possibly work for multiple selections.
    You should split the cell expansion/compression notification into 2 distinct blocks (no need to keep track of selectedIndexPath, more robust code):

    Expand

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

    Contract

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

    Selection is destroyed by selectRowAtIndexPath

    This prevents didDeselectRowAtIndexPath from ever being invoked. A workaround is to cache the entire selection, not individual indexes, and to restore such selection after reload.

    Complete code:

    Notice when and how cacheSelectedRows is maintained. This uses a plain UITableViewCell. All it needs is a 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)
                }
            }
        }
    }
    

    Demo


    ► Find this solution on GitHub and additional details on Swift Recipes.

    0 讨论(0)
  • 2021-01-23 06:58

    I didn't find answer, why the strange behavior of textView and cell height is happening, but I have solution for my problem.

    So it looks like tableView.estimatedRowHeight = 160 and tableView.rowHeight = UITableViewAutomaticDimension don't respect textView's maximum number of lines for all cells. cellForRow works fine, it sets the limitation, but the rows height is sometimes expanded and sometimes contracted.

    So I unwrapped textView and the bottom separator from StackView, replaced TextView with Label and set autolayaut constraints. Now it works fine, without strange behavior.

    0 讨论(0)
提交回复
热议问题