Update: It looks like the tableView.estimatedRowHeight
setting is somehow related to the problem, since the variance of the problem changes as the number changes, and setting it to 9999 makes it "go away" but that seems super hacky. The 9999 also breaks the animations I intended to do on the show/hide. 9999 also breaks the scrollbars funtionality. See the discussion thread below for additional details and full context.
I have a view controller which holds two Container Views
. Each container view holds a UITableView
controller. They're orientated vertically each taking up the full height.
The container on the right side has a width of 100 and starts off screen with the trailing constraint set to -100 which allows the other container to fill the whole screen initially.
The table on the left has automatic adjusting cell heights using UITableViewAutomaticDimension
since when the hidden view is shown, some text on two lines may need to wrap to the next line.
When I change the constraint to be 0 and show the view, if I'm not at the top of the list, rather than expanding what's visible on the screen, it seems to be expanding everything, thus pushing what was on the screen down, further than it should be going.
What's weird though, is subsequent expand/collapses work as expected, only adjusting what is visible.
I've attached a video a video showing the issue, I'm just trying to connect things up and get the sizing working right now, the content in the right view will be different eventually.
The following is what's happening in the video
It doesn't matter how far down the list I go, the same behaviour happens, getting worse as I go further down.
I'm adjusting the constraints like this on a button press for now.
if self.timeContainerConstraint.constant == 0 {
self.timeContainerConstraint.constant = -90.0
} else {
self.timeContainerConstraint.constant = 0.0
}
Does anyone know why the content is jumping when I scroll down the list and expand the first time, but not jumping on subsequent attempts?
As you have variable cell heights, the tableview can't correctly calculate the scroll offset when its frame changes. It has to rely on the estimated row height, but as you have a fixed value for this, the more cells 'above' the current scroll position, the greater the error between the estimated and the actual value.
I was able to solve this by caching the cell heights in order to return a more accurate estimated height using estimatedHeightForRowAt:
var cellHeights = [IndexPath:CGFloat]()
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let frame = tableView.rectForRow(at: indexPath)
self.cellHeights[indexPath] = frame.size.height
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return self.cellHeights[indexPath] ?? 140.0
}
Using this approach, the expansion and contraction of the side bar didn't affect the table's position. I was able to animate the constraint change for a nice smooth reveal and the table didn't 'jump', even if the table was scrolling while the side bar was opened.
My sample project is here