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
Also remember that you need to use proper UICollectionviewScrollPosition value. Please see code below for clarification:
typedef NS_OPTIONS(NSUInteger, UICollectionViewScrollPosition) {
UICollectionViewScrollPositionNone = 0,
/* For a view with vertical scrolling */
// The vertical positions are mutually exclusive to each other, but are bitwise or-able with the horizontal scroll positions.
// Combining positions from the same grouping (horizontal or vertical) will result in an NSInvalidArgumentException.
UICollectionViewScrollPositionTop = 1 << 0,
UICollectionViewScrollPositionCenteredVertically = 1 << 1,
UICollectionViewScrollPositionBottom = 1 << 2,
/* For a view with horizontal scrolling */
// Likewise, the horizontal positions are mutually exclusive to each other.
UICollectionViewScrollPositionLeft = 1 << 3,
UICollectionViewScrollPositionCenteredHorizontally = 1 << 4,
UICollectionViewScrollPositionRight = 1 << 5
};
Sometimes collectionView(_:didSelectItemAt:)
is either not called on the main thread, or blocks it, causing scrollToItem(at:at:animated:)
to not do anything.
Work around this by doing:
DispatchQueue.main.async {
collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
}
This is based on @Womble's answer, all credit goes to them:
The method viewDidLayoutSubviews()
gets called repeatedly. For me (iOS 11.2) the first time it gets called the collectionView.contentSize
is {0,0}
. The second time, the contentSize
is correct. Therefore, I had to add a check for this:
var needsDelayedScrolling = false
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.needsDelayedScrolling = true
// ...
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if self.needsDelayedScrolling && collectionView.contentSize.width > 0 {
self.needsDelayedScrolling = false
self.collectionView!.scrollToItem(at: someIndexPath,
at: .centeredVertically,
animated: false)
}
}
}
After adding that extra && collectionView.contentSize.width > 0
it works beautifully.