ios iOS6 UICollectionView 和 UIPageControl - 如何获取可见单元格?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13176333/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS6 UICollectionView and UIPageControl - How to get visible cell?
提问by gazzola
While studying iOS6 new features I got a question about UICollectionView.
I am currently testing it with Flow layout and the scroll direction set to horizontal, scrolling and paging enabled. I've set its size to exactly the same as my custom's cells, so it can show one at a time, and by scrollig it sideways, the user would see the other existing cells.
在学习 iOS6 新功能时,我有一个关于UICollectionView的问题。
我目前正在使用 Flow 布局和滚动方向设置为水平、滚动和分页来测试它。我已将其大小设置为与我自定义的单元格完全相同,因此它可以一次显示一个,并且通过将其向侧面滚动,用户将看到其他现有单元格。
It works perfectly.
它完美地工作。
Now I want to add and UIPageControlto the collection view I made, so it can show up which cell is visible and how many cells are there.
现在我想将UIPageControl添加到我创建的集合视图中,以便它可以显示哪个单元格可见以及有多少个单元格。
Building up the page control was rather simple, frame and numberOfPages defined.
构建页面控件相当简单,frame 和 numberOfPages 已定义。
The problem I am having, as the question titles marks, is how to get which cell is currently visible in the collection view, so it can change the currentPage of the page control.
正如问题标题所标记的,我遇到的问题是如何获取当前在集合视图中可见的单元格,以便它可以更改页面控件的 currentPage。
I've tried delegate methods, like cellForItemAtIndexPath, but it is made to load cells, not show them. didEndDisplayingCell triggers when a cell its not displayed anymore, the opposite event of what I need.
我试过委托方法,比如 cellForItemAtIndexPath,但它是用来加载单元格的,而不是显示它们。didEndDisplayingCell 在单元格不再显示时触发,这是我需要的相反事件。
Its seems that -visibleCells and -indexPathsForVisibleItems, collection view methods, are the correct choice for me, but I bumped into another problem. When to trigger them?
看起来集合视图方法 -visibleCells 和 -indexPathsForVisibleItems 是我的正确选择,但我遇到了另一个问题。什么时候触发它们?
Thanks in advance, hope I made myself clear enough so you guys can understand me!
在此先感谢,希望我说得足够清楚,以便你们能理解我!
回答by Sendoa
You must setup yourself as UIScrollViewDelegate
and implement the scrollViewDidEndDecelerating:
method like so:
您必须将自己设置为UIScrollViewDelegate
并实现如下scrollViewDidEndDecelerating:
方法:
Objective-C
目标-C
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGFloat pageWidth = self.collectionView.frame.size.width;
self.pageControl.currentPage = self.collectionView.contentOffset.x / pageWidth;
}
Swift
迅速
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageWidth = self.collectionView.frame.size.width
pageControl.currentPage = Int(self.collectionView.contentOffset.x / pageWidth)
}
回答by Not Randy Marsh
I struggled with this for a while as well, then I was advised to check out the parent classes of UICollectionView. One of them happens to be UIScrollViewand if you set yourself up as a UIScrollViewDelegate, you get access to very helpful methods such as scrollViewDidEndDecelerating, a great place to update the UIPageControl.
我也为此挣扎了一段时间,然后我被建议检查 UICollectionView 的父类。其中之一恰好是UIScrollView,如果您将自己设置为UIScrollViewDelegate,您可以访问非常有用的方法,例如scrollViewDidEndDecelerating,这是更新 UIPageControl 的好地方。
回答by Nikolay Shubenkov
I would recommend a little tuned calculation and handling as it will update page control immediately in any scroll position with better accuracy.
我建议稍微调整计算和处理,因为它会在任何滚动位置立即更新页面控制,并具有更高的准确性。
The solution below works with any scroll view or it subclass (UITableView UICollectionView and others)
下面的解决方案适用于任何滚动视图或其子类(UITableView UICollectionView 等)
in viewDidLoad method write this
在 viewDidLoad 方法中写这个
scrollView.delegate = self
then use code for your language:
然后使用您的语言代码:
Swift 3
斯威夫特 3
func scrollViewDidScroll(_ scrollView: UIScrollView)
{
let pageWidth = scrollView.frame.width
pageControl.currentPage = Int((scrollView.contentOffset.x + pageWidth / 2) / pageWidth)
}
Swift 2:
斯威夫特 2:
func scrollViewDidScroll(scrollView: UIScrollView)
{
let pageWidth = CGRectGetWidth(scrollView.frame)
pageControl.currentPage = Int((scrollView.contentOffset.x + pageWidth / 2) / pageWidth)
}
Objective C
目标 C
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat pageWidth = self.collectionView.frame.size.width;
self.pageControl.currentPage = (self.collectionView.contentOffset.x + pageWidth / 2) / pageWidth;
}
回答by Ramesh
Another option with less code is to use visible item index path and set the page control.
另一个代码较少的选项是使用可见项索引路径并设置页面控件。
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
self.pageControl.currentPage = [[[self.collectionView indexPathsForVisibleItems] firstObject] row];
}
回答by Ramdhas
- Place PageControlin your view or set by Code.
- Set UIScrollViewDelegate
- In Collectionview-> cellForItemAtIndexPath (Method) add the below code for calculate the Number of pages,
- 将PageControl放在您的视图中或由代码设置。
- 设置UIScrollViewDelegate
- 在Collectionview-> cellForItemAtIndexPath (Method) 中添加以下代码来计算页数,
int pages =floor(ImageCollectionView.contentSize.width/ImageCollectionView.frame.size.width); [pageControl setNumberOfPages:pages];
int pages =floor(ImageCollectionView.contentSize.width/ImageCollectionView.frame.size.width); [pageControl setNumberOfPages:pages];
Add the ScrollView Delegatemethod,
添加ScrollView 委托方法,
pragma mark - UIScrollVewDelegate for UIPageControl
pragma mark - UIScrollVewDelegate 用于 UIPageControl
- (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);
}
回答by Dallas Johnson
I know this is an old one but I've just needed to implement this sort of feature again and have a bit to add which gives a more complete answer.
我知道这是一个旧的,但我只需要再次实现这种功能并添加一些内容以提供更完整的答案。
Firstly:Using scrollViewDidEndDecelerating
assumes that the user lifted their finger while dragging (more like a flick action) and therefore there is a deceleration phase. If the user drags without lifting the finger the UIPageControl
will still indicate the old page from before the drag began. Instead using the scrollViewDidScroll
callback means that the view is updated both after dragging and flicking and also during dragging and scrolling so it feels much more responsive and accurate for the user.
首先:使用scrollViewDidEndDecelerating
假设用户在拖动时抬起手指(更像是轻弹动作),因此有一个减速阶段。如果用户在不抬起手指的情况下进行拖动,UIPageControl
则仍将指示拖动开始前的旧页面。相反,使用scrollViewDidScroll
回调意味着视图在拖动和轻弹之后以及在拖动和滚动期间都会更新,因此对用户来说感觉更加灵敏和准确。
Secondly:Relying on the pagewidth
for calculating the selected index assumes all the cells have the same width and that there is one cell per screen. taking advantage of the indexPathForItemAtPoint
method on UICollectionView
gives a more resilient result which will work for different layouts and cell sizes. The implementation below assumes the centre of the frame is the desired cell to be represented in the pagecontrol
. Also if there are intercell spacings there will times during scrolling when the selectedIndex could be nil or optional so this needs to be checked and unwrapped before setting on the pageControl.
其次:依赖于pagewidth
计算所选索引假设所有单元格具有相同的宽度并且每个屏幕有一个单元格。利用indexPathForItemAtPoint
on的方法可以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
}
}
One more thing - set the number of pages on the UIPageControl
with something like this:
还有一件事 -UIPageControl
用这样的东西设置页数:
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
self.pageControl.numberOfPages = 20
return self.pageControl.numberOfPages
}
回答by Michael
Simple Swift
简单的斯威夫特
public func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
pageControl.currentPage = (collectionView.indexPathsForVisibleItems().first?.row)!
}
UIScrollViewDelegate
is already implemented if you implement UICollectionViewDelegate
UIScrollViewDelegate
如果您实施,则已经实施 UICollectionViewDelegate