I have created a CollectionView
Control and filled it with images. Now I want to scroll to item at a particular index on start. I have tried out scrollToItemA
As of iOS 9.3, Xcode 8.2.1, Swift 3:
Calling scrollToItem(at:)
from viewWillAppear()
is still broken, particularly if you are using Section Headers/Footers, Auto Layout, Section Insets.
Even if you call setNeedsLayout()
and layoutIfNeeded()
on the collectionView
, the behavior is still borked. Putting the scrolling code in to an animation block doesn't work reliably.
As indicated in the other answers, the solution is to only call scrollToItem(at:)
once you are sure everything has been laid out. i.e. in viewDidLayoutSubviews()
.
However, you need to be selective; you don't want to perform scrolling every time viewWillLayoutSubviews()
is called. So a solution is to set a flag in viewWillAppear()
, and act it on it in viewDidLayoutSubviews()
.
i.e.
fileprivate var needsDelayedScrolling = false
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
self.needsDelayedScrolling = true
// ...
}
override func viewDidLayoutSubviews()
{
super.viewDidLayoutSubviews()
if self.needsDelayedScrolling {
self.needsDelayedScrolling = false
self.collectionView!.scrollToItem(at: someIndexPath,
at: .centeredVertically,
animated: false)
}
}
}