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.
It works perfectly.
Now I want to add and UIPageControl to the collection view I made, so it can show up which cell is visible and how many cells are there.
Building up the page control was rather simple, frame and numberOfPages defined.
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.
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.
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?
Thanks in advance, hope I made myself clear enough so you guys can understand me!
You must setup yourself as UIScrollViewDelegate
and implement the scrollViewDidEndDecelerating:
method like so:
Objective-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)
}
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 UIScrollView and 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.
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)
in viewDidLoad method write this
scrollView.delegate = self
then use code for your language:
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)
}
Objective C
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat pageWidth = self.collectionView.frame.size.width;
self.pageControl.currentPage = (self.collectionView.contentOffset.x + pageWidth / 2) / pageWidth;
}
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];
}
int pages =floor(ImageCollectionView.contentSize.width/ImageCollectionView.frame.size.width); [pageControl setNumberOfPages:pages];
Add the ScrollView Delegate method,
- (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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With