UICollectionView auto scroll to cell at IndexPath

Before loading the collection view user sets the number of image in the array of collection view. All of the cells don't fit on the screen. I have 30 cells and only 6 on the screen.

The question: How to scroll to the cell with desired image automatically at the load of UICollectionView?

123291 次浏览

最新编辑答案:

viewDidLayoutSubviews中加入这个

SWIFT

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let indexPath = IndexPath(item: 12, section: 0)
self.collectionView.scrollToItem(at: indexPath, at: [.centeredVertically, .centeredHorizontally], animated: true)
}

通常情况下,.centerVertically是这种情况

目的

-(void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:12 inSection:0];
[self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically | UICollectionViewScrollPositionCenteredHorizontally animated:NO];
}

旧版 iOS 的老问题

viewWillAppear中添加以下内容:

[self.view layoutIfNeeded];
[self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO];

我完全同意上述答案。唯一的问题是,对我来说,解决方案是在 viewDidAppear 中设置代码

viewDidAppear
{
[self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:YES];
}

当我使用 viewWillAppear 时,滚动不起作用。

我发现在 viewWillAppear中滚动可能不能可靠地工作,因为集合视图还没有完成它的布局; 您可能滚动到错误的项目。

我还发现,在 viewDidAppear中滚动将导致非滚动视图的瞬间闪烁可见。

而且,如果您每次通过 viewDidLayoutSubviews滚动,用户将无法手动滚动,因为一些集合布局导致子视图布局每次您滚动。

以下是我发现的可靠方法:

目标丙:

- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];


// If we haven't done the initial scroll, do it once.
if (!self.initialScrollDone) {
self.initialScrollDone = YES;
    

[self.collectionView scrollToItemAtIndexPath:self.myInitialIndexPath
atScrollPosition:UICollectionViewScrollPositionRight animated:NO];
}
}

斯威夫特:

 override func viewWillLayoutSubviews() {


super.viewWillLayoutSubviews()


if !self.initialScrollDone {


self.initialScrollDone = true
self.testNameCollectionView.scrollToItem(at:selectedIndexPath, at: .centeredHorizontally, animated: true)
}


}

这似乎对我有用,它与另一个答案相似,但有一些明显的区别:

- (void)viewDidLayoutSubviews
{
[self.collectionView layoutIfNeeded];
NSArray *visibleItems = [self.collectionView indexPathsForVisibleItems];
NSIndexPath *currentItem = [visibleItems objectAtIndex:0];
NSIndexPath *nextItem = [NSIndexPath indexPathForItem:someInt inSection:currentItem.section];


[self.collectionView scrollToItemAtIndexPath:nextItem atScrollPosition:UICollectionViewScrollPositionNone animated:YES];
}

斯威夫特:

your_CollectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: true)

Swift 3

let indexPath = IndexPath(row: itemIndex, section: sectionIndex)


collectionView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition.right, animated: true)

卷轴位置:

UICollectionViewScrollPosition.CenteredHorizontally / UICollectionViewScrollPosition.CenteredVertically

You can use GCD to dispatch the scroll into the next iteration of main run loop in viewDidLoad to achieve this behavior. The scroll will be performed before the collection view is showed on screen, so there will be no flashing.

- (void)viewDidLoad {
dispatch_async (dispatch_get_main_queue (), ^{
NSIndexPath *indexPath = YOUR_DESIRED_INDEXPATH;
[self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
});
}

所有的答案在这里-hacks。我已经找到了更好的方法来滚动在 relodData 之后的某个地方的集合视图:
子类集合视图布局不管你使用什么布局,重写方法 prepareLayout,超级调用之后设置不管你需要什么偏移量。
例如: https://stackoverflow.com/a/34192787/1400119

我建议在 collectionView: willDisplay:中这样做,然后您可以确保收集视图委托交付一些东西。 以下是我的例子:

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
/// this is done to set the index on start to 1 to have at index 0 the last image to have a infinity loop
if !didScrollToSecondIndex {
self.scrollToItem(at: IndexPath(row: 1, section: 0), at: .left, animated: false)
didScrollToSecondIndex = true
}
}

作为上面提到的替代品。 数据加载后调用:

斯威夫特

collectionView.reloadData()
collectionView.layoutIfNeeded()
collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .right)