UICollectionView自动滚动到IndexPath的单元格

Ale*_*erZ 91 ios uicollectionview

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

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

bow*_*ann 161

新编辑答案:

添加此内容 viewDidLayoutSubviews

迅速

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

通常情况.centerVertically是这样的

ObjC

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

旧答案适用于较旧的iOS

添加此内容viewWillAppear:

[self.view layoutIfNeeded];
[self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO];
Run Code Online (Sandbox Code Playgroud)

  • 这在iOS 7.1上无法可靠地工作,并且可能导致集合视图显示为黑屏.我也不想像下面的viewDidLayoutSubviews中的解决方案一样维护状态.我所做的只是在调用scrollToItemAtIndexPath之前执行了[self.view layoutIfNeeded] (9认同)
  • 在最新的iOS(9/10)中对我不起作用 (8认同)
  • 这正是我想要使用的.我有数组中对象的编号,我知道该对象的名称.但是不知道如何把正确的indexPath ...任何想法? (4认同)
  • 您可以轻松创建`indexPath`:`[NSIndexPath indexPathForItem:numberOfTheObject inSection:sectionNumber]` (4认同)
  • 有一些错误.但后来我把所有提到的代码放在(void)viewDidLayoutSubviews {}中,现在它工作正常.Thanx Bogdan. (3认同)

Len*_*enK 77

我发现滚动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];
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这在iOS 8.3中对我不起作用.不得不调用`[self.collectionView layoutIfNeeded];`之前,在`viewDidLoad`中执行此操作时也可以. (4认同)

小智 13

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

viewDidAppear 
{
    [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:YES];
}
Run Code Online (Sandbox Code Playgroud)

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

  • viewDidAppear的缺点是你看到集合视图正在移动/闪烁,视图已经出现(顾名思义)......我真的好奇为什么Apple没有以更好的方式设计这个不那么不寻常的情况,viewDidLayoutSubviews的方式是有点尴尬 (2认同)

gre*_*use 11

这似乎对我有用,它与另一个答案类似,但有一些明显的差异:

- (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];
}
Run Code Online (Sandbox Code Playgroud)


Raj*_*han 11

迅速:

your_CollectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: true)
Run Code Online (Sandbox Code Playgroud)

斯威夫特3

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

collectionView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition.right, animated: true)
Run Code Online (Sandbox Code Playgroud)

滚动位置:

UICollectionViewScrollPosition.CenteredHorizontally / UICollectionViewScrollPosition.CenteredVertically
Run Code Online (Sandbox Code Playgroud)


小智 8

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

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


Eik*_*ike 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
    }
}
Run Code Online (Sandbox Code Playgroud)


nCo*_*d3d 7

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

迅速

collectionView.reloadData()
collectionView.layoutIfNeeded()
collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .right)
Run Code Online (Sandbox Code Playgroud)