I have a view at the top of a view controller, and a tableview underneath it.
I've made it such that as the tableview is scrolled up the top view scrolls up too, up to a maximum amount, of lets say 50 points.
The tableview also has a top inset of 50:
tableView = UIEdgeInsets(top: 50, left: 0, bottom: 0, right: 0)
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let scrollViewYOffset = ...
topViewHeightConstraint.constant = max(minTopViewHeight, minTopViewHeight - scrollViewYOffset)
}
contentInset
As the contentInset
is what is causing the tableview to ping back to the wrong point, I simply needed to adjust the content inset as the tableview was scrolled up/down.
Here is some example code of what I did:
let maxPointsTopViewCanMoveUp: CGFloat = 50
let topInset = abs(min(max(-maxPointsTopViewCanMoveUp, scrollView.contentOffset.y), 0))
scrollView.contentInset = UIEdgeInsets(top: topInset, left: 0, bottom: 0, right: 0)
scrollView.scrollIndicatorInsets = UIEdgeInsets(top: topInset, left: 0, bottom: 0, right: 0)
let amountToMoveTopViewUp = maxPointsTopViewCanMoveUp - topInset
topViewToSuperviewTopConstraint.constant = amountToMoveTopViewUp
This is called from the scrollViewDidScroll
of the tableview.
It means that when there are too few cells in the tableview to fill the content, the top the tableview sticks in the place it had been scrolled up to (i.e. the amount it had pushed up the top view).