UITableView jumps after running / endUpdates when using UITableViewAutomaticDimension

Problem : when I am in the bottom UITableView (and only when in the bottom) and tableView.beginUpdates()/ tableView.endUpdates()is called, UITableViewit bounces a little. I do not want this to be done.

Customization: I have a UITableViewc UITableViewCellsthat will have different sizes, and I use UITableViewAutomaticDimensionto sort the cells.

Example: When I'm at the bottom UITableView, and I select the cell, which then causes a tableView.beginUpdates()/ tableView.endUpdates(), UITableViewscrolls / jumps up slightly.

Has anyone found a way to prevent jumping after calling tableView.beginUpdates()/ tableView.endUpdates(), but in the end UITableView?

While I am calculating all of mine UITableViewCellsmanually, I would prefer not to do this because I would like to take advantage UITableViewAutomaticDimension.

Code

Here is the code showing what happens between tableView.beginUpdates()/ tableView.endUpdates():

    tableView.beginUpdates()
    cell!.setNeedsUpdateConstraints()
    cell!.updateConstraintsIfNeeded()
    cell!.setNeedsLayout()
    cell!.layoutIfNeeded()
    tableView.endUpdates()

My viewWillAppear:

public override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    self.tableView.estimatedRowHeight = 150.0
    self.tableView.rowHeight = UITableViewAutomaticDimension


    self.tableView.reloadData()
    //Bug in 8.0+ forces us to call three extra methods to get dynamic cell heights to work correctly...
    self.tableView.setNeedsLayout()
    self.tableView.layoutIfNeeded()
    self.tableView.reloadData()
}

My heightForRow:

public override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {

    return UITableViewAutomaticDimension

}

Update : the removal of cell!.setNeedsUpdateConstraints(), cell!.updateConstraintsIfNeeded(), cell!.setNeedsLayout()and cell!.layoutIfNeeded() from tableView.beginUpdates()/ tableView.endUpdates()means to stop jumping, but then my cell is not the size ...

Change . This happens only at the bottom UITableView .

+4
source share
3 answers

It should be simple:

UITableView UIScrollView. UIScrollView, . .

.

0

, , . endUpdates func scrollViewDidScroll(_ scrollView: UIScrollView), . reset , , , .

, , , , , , . , - , .

, , :

, , , , , , . .

, , , . . , ( , ).

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        // Modify data source
        let currentResult = results[indexPath.row] // Fetch object
        let toggledResult = (object: currentResult.object, extended: !currentResult.extended) // Toggle being extended
        results[indexPath.row] = toggledResult // Assign it back to array

        // Find the cell
        if let cell = tableView.cellForRow(at: indexPath) as? ResultTableViewCell {
            let currentFooterView = tableView.tableFooterView // Steal the current footer view
            let newView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: tableView.bounds.width, height: tableView.bounds.height*2.0)) // Create a new footer view with large enough height (Really making sure it is large enough)
            if let currentFooterView = currentFooterView {
                // Put the current footer view as a subview to the new one if it exists (this was not really tested)
                currentFooterView.frame.origin = .zero // Just in case put it to zero
                newView.addSubview(currentFooterView) // Add as subview
            }
            tableView.tableFooterView = newView // Assign a new footer

            // Doing standard animations
            UIView.animate(withDuration: 0.3, animations: {
                cell.resultObject = toggledResult // This will trigger internal cell animations

                // Standard refresh
                tableView.beginUpdates()
                tableView.endUpdates()
                tableView.tableFooterView = currentFooterView // Put the footer view back
            })
        }

    }

:

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        // Modify data source
        let currentResult = results[indexPath.row] // Fetch object
        let toggledResult = (object: currentResult.object, extended: !currentResult.extended) // Toggle being extended
        results[indexPath.row] = toggledResult // Assign it back to array

        // Find the cell
        if let cell = tableView.cellForRow(at: indexPath) as? ResultTableViewCell {
            // Doing standard animations
            UIView.animate(withDuration: 0.3, animations: {
                cell.resultObject = toggledResult // This will trigger internal cell animations

                // Standard refresh
                tableView.beginUpdates()
                tableView.endUpdates()
            })
        }

    }

, . , ( ). , , , .

0

, . , :

,

  • (, )
  • tableView.beginUpdates() tableView.endUpdates()

- .

, , tableView View

?

, :

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let cell = tableView.cellForRow(at: indexPath)
        cell.heightConstraint = 100
        UIView.animate(withDuration: 0.15, animations: {

            self.view.layoutIfNeeded()
            self.tableView.beginUpdates()
            self.tableView.endUpdates()
        }, completion: nil)
}

, , View tableView.endUpdates().

:

let currentScrollPos : CGFloat?

override func scrollViewDidScroll(_ scrollView: UIScrollView) {
        // Force the tableView to stay at scroll position until animation completes
        if (currentScrollPos != nil){
            tableView.setContentOffset(CGPoint(x: 0, y: currentScrollPos!), animated: false)
        }
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let cell = tableView.cellForRow(at: indexPath)
        cell.heightConstraint = 100
        UIView.animate(withDuration: 0.15, animations: {

            self.currentScrollPos = self.tableView.contentOffset.y

            self.view.layoutIfNeeded()
            self.tableView.beginUpdates()
            self.tableView.endUpdates()

            self.currentScrollPos = nil
        }, completion: nil)
}
0

Source: https://habr.com/ru/post/1616437/


All Articles