iOS6的UICollectionView和UIPageControl – 如何获得可见的单元格?

在学习iOS6新function时,我得到了一个关于UICollectionView的问题。
我目前正在testingstream布局和滚动方向设置为水平,滚动和分页启用。 我已经将其大小设置为与我的自定义单元格完全相同,因此它可以一次显示一个单元格,通过向侧面滚动,用户将看到其他现有单元格。

它完美的作品。

现在我想添加和UIPageControl到我做的集合视图,所以它可以显示哪个单元格是可见的,有多less个单元格。

构build页面控件相当简单,定义了frame和numberOfPages。

问题标题所指出的问题是如何获取当前在集合视图中可见的单元格,以便可以更改页面控件的当前页面。

我已经尝试委托方法,如cellForItemAtIndexPath,但它是加载单元格,而不是显示它们。 didEndDisplayingCell在单元格不再显示时触发,与我所需要的相反。

它似乎-visibleCells和-indexPathsForVisibleItems,集合视图方法,是我的正确select,但我遇到了另一个问题。 什么时候触发他们?

在此先感谢,希望我能让自己清楚明白,以便你们能理解我!

您必须将自己设置为UIScrollViewDelegate并像下面这样实现scrollViewDidEndDecelerating:方法:

Objective-C的

 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { CGFloat pageWidth = self.collectionView.frame.size.width; self.pageControl.currentPage = self.collectionView.contentOffset.x / pageWidth; } 

迅速

 func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { let pageWidth = self.collectionView.frame.size.width pageControl.currentPage = Int(self.collectionView.contentOffset.x / pageWidth) } 

我也苦苦挣扎了一段时间,然后build议查看UICollectionView的父类。 其中一个恰好是UIScrollView ,如果您将自己设置为UIScrollViewDelegate ,则可以访问非常有用的方法,例如scrollViewDidEndDecelerating ,这是更新UIPageControl的好地方。

我会build议一些调整计算和处理,因为它会更快地更新页面控制在任何滚动位置更准确。

下面的解决scheme适用于任何滚动视图或它的子类(UITableView UICollectionView和其他)

在viewDidLoad方法中写这个

 scrollView.delegate = self 

然后使用您的语言的代码:

Swift 3

 func scrollViewDidScroll(_ scrollView: UIScrollView) { let pageWidth = scrollView.frame.width pageControl.currentPage = Int((scrollView.contentOffset.x + pageWidth / 2) / pageWidth) } 

Swift 2:

 func scrollViewDidScroll(scrollView: UIScrollView) { let pageWidth = CGRectGetWidth(scrollView.frame) pageControl.currentPage = Int((scrollView.contentOffset.x + pageWidth / 2) / pageWidth) } 

目标C

 - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat pageWidth = self.collectionView.frame.size.width; self.pageControl.currentPage = (self.collectionView.contentOffset.x + pageWidth / 2) / pageWidth; } 

使用较less代码的另一个选项是使用可见项索引path并设置页面控制。

 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { self.pageControl.currentPage = [[[self.collectionView indexPathsForVisibleItems] firstObject] row]; } 
  1. PageControl放置在您的视图中或由代码设置。
  2. 设置UIScrollViewDelegate
  3. Collectionview – > cellForItemAtIndexPath(Method)中添加下面的代码来计算页数,

int pages = floor(ImageCollectionView.contentSize.width / ImageCollectionView.frame.size.width); [pageControl setNumberOfPages:pages];

添加ScrollView委托方法,

编译标记 – 用于UIPageControl的UIScrollVewDelegate

 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { CGFloat pageWidth = ImageCollectionView.frame.size.width; float currentPage = ImageCollectionView.contentOffset.x / pageWidth; if (0.0f != fmodf(currentPage, 1.0f)) { pageControl.currentPage = currentPage + 1; } else { pageControl.currentPage = currentPage; } NSLog(@"finishPage: %ld", (long)pageControl.currentPage); } 

我知道这是一个旧的,但我只需要再次实现这种function,并有一点补充,这给了一个更完整的答案。

首先:使用scrollViewDidEndDecelerating假定用户在拖动时抬起手指(更像是轻弹动作),因此存在减速阶段。 如果用户拖动手指, UIPageControl仍然会在拖动开始之前指示旧页面。 而使用scrollViewDidScrollcallback意味着视图在拖拽和轻拂后以及在拖拽和滚动期间都被更新,因此对用户来说,感觉更加敏感和准确。

其次:依靠计算所选索引的页面宽度,假定所有单元具有相同的宽度,并且每个屏幕有一个单元。 利用indexPathForItemAtPoint上的indexPathForItemAtPoint方法提供了一个更UICollectionView结果,这将适用于不同的布局和单元大小。 下面的实现假设框架的中心是页面pagecontrol要表示的所需单元格。 另外,如果有单元间距,那么在滚动期间,当selectedIndex可能是零或可选的时候会有时间,所以在设置pageControl之前需要检查和解包。

  func scrollViewDidScroll(scrollView: UIScrollView) { let contentOffset = scrollView.contentOffset let centrePoint = CGPointMake( contentOffset.x + CGRectGetMidX(scrollView.frame), contentOffset.y + CGRectGetMidY(scrollView.frame) ) if let index = self.collectionView.indexPathForItemAtPoint(centrePoint){ self.pageControl.currentPage = index.row } } 

还有一件事 – 在UIPageControl上设置页面的数量,如下所示:

  func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { self.pageControl.numberOfPages = 20 return self.pageControl.numberOfPages } 

简单的斯威夫特

 public func scrollViewDidEndDecelerating(scrollView: UIScrollView) { pageControl.currentPage = (collectionView.indexPathsForVisibleItems().first?.row)! } 

如果您实现UICollectionViewDelegate则已经实现了UIScrollViewDelegate