问题
i have a collectionview that i am trying to scroll programatically. the problem being that if the cell i want to scroll to is visible in the collection view it doesn't scroll it to the centre. so for the image below the lower cell is item 1. and it does not scroll to it but it will scroll past item 1 to item 2.
i have been trying to use UICollectionVieScrollPosition.CenterVertically but this does not seem to work.
self.collectionView?.scrollToItem(at: IndexPath(row: 1, section: 0), at: UICollectionViewScrollPosition.centeredVertically, animated: true)
is there a way around this to force the scrolling of cells that are visible to the centre of the collection?
回答1:
the best way i found to do this is to not use scrollToItem but to get the CGRect of the index and then make that visible.
let rect = self.collectionView.layoutAttributesForItem(at: IndexPath(row: 5, section: 0))?.frame
self.collectionView.scrollRectToVisible(rect!, animated: false)
回答2:
I'm trying to delay it with 0.1s. For my case, looks good for now:
collectionView.collectionViewLayout.invalidateLayout() //just in case, iOS10 may crash btw.
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
}
Update:
ok, turns out that I'm using layout.estimatedItemSize and autolayout to calculate the width of my cells, that's why I have this problem.
That says, for me, it's because of CollectionView's dynamic sizing.
After I back to calculate the width manually, everything works fine. (by using -collectionView:layout:sizeForItemAt:)
回答3:
First of all you need to find the center of the CollectionView and this is how it can be done:
private func findCenterIndex() -> Int {
let center = self.view.convert(numberCollectionView.center, to: self.numberCollectionView)
let row = numberCollectionView!.indexPathForItem(at: center)?.row
guard let index = row else {
return 0
}
return index
}
then get the row number under your scrollToItem and it should work:
collectionView.scrollToItem(at: IndexPath(item: findCenterIndex(), section: 0), at: .centeredVertically, animated: false)
call it from viewDidLayoutSubviews()
回答4:
If itemSize is too small,scrollToItemnot working.
siwft
collectionView.contentOffset = offset
I use this fixed
回答5:
It seems that you have centred the first cell in your UICollectionView vertically.
I have found that if I centred the first cell by adding an inset through the contentInset property of UICollectionView, its scrollToItem(at:at:animated:) method also doesn't work for cells already visible.
However, if I centred the first cell by adding an inset through the sectionInset property of UICollectionViewFlowLayout, then scrollToItem(at:at:animated:) works for visible cells.
Specifically, in code:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Padding needed to allow the first and last cells to be centred vertically.
let insectHeight = (collectionView.bounds.height - collectionViewFlowLayout.itemSize.height) / 2.0
// This way is disabled because scrollToItem doesn't work for visible cells.
// collectionView.contentInset = UIEdgeInsets(top: insectHeight,
// left: 0,
// bottom: insectHeight,
// right: 0)
// This is the way for scrollToItem to work for visible cells.
collectionViewFlowLayout.sectionInset = UIEdgeInsets(top: insectHeight,
left: 0,
bottom: insectHeight,
right: 0)
}
My guess is that contentInset is a property UICollectionView inherited from UIScrollView, and the way scrollToItem(at:at:animated:) works out the offset seems incompatible to the way contentInset is used by UIScrollView.
来源:https://stackoverflow.com/questions/41413240/uicollectionviewscrollposition-not-working