115

在加载集合视图之前,用户设置集合视图数组中的图像数量。所有单元格都不适合屏幕。我有 30 个单元格,屏幕上只有 6 个。

问题:如何在加载 UICollectionView 时自动滚动到具有所需图像的单元格?

4

9 回答 9

181

新的,已编辑的答案:

添加这个viewDidLayoutSubviews

迅速

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];
于 2013-04-13T09:01:16.377 回答
104

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

我还发现滚动viewDidAppear会导致未滚动视图的瞬间闪烁可见。

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

这是我发现可靠的工作:

目标 C:

- (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)
    }

}
于 2014-10-08T00:38:33.127 回答
17

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

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

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

于 2014-07-22T10:25:40.080 回答
13

迅速:

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

斯威夫特 3

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

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

滚动位置:

UICollectionViewScrollPosition.CenteredHorizontally / UICollectionViewScrollPosition.CenteredVertically
于 2015-12-11T07:27:30.987 回答
12

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

- (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];
}
于 2015-05-28T18:56:01.213 回答
10

您可以使用 GCD 将滚动分派到 viewDidLoad 中的主运行循环的下一次迭代以实现此行为。滚动将在集合视图显示在屏幕上之前执行,因此不会闪烁。

- (void)viewDidLoad {
    dispatch_async (dispatch_get_main_queue (), ^{
        NSIndexPath *indexPath = YOUR_DESIRED_INDEXPATH;
        [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
    });
}
于 2016-05-21T12:37:53.900 回答
7

作为上述的替代方案。数据加载后调用:

迅速

collectionView.reloadData()
collectionView.layoutIfNeeded()
collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .right)
于 2019-09-11T14:44:01.487 回答
7

我建议这样做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
    }
}
于 2017-11-06T15:03:43.723 回答
2

这里的所有答案 - 黑客。在 relaodData 之后,我找到了在某处滚动集合视图的更好方法:
子类集合视图布局你使用什么布局,覆盖方法 prepareLayout,在超级调用之后设置你需要的偏移量。
例如:https ://stackoverflow.com/a/34192787/1400119

于 2016-07-29T14:33:04.500 回答