UICollectionView with Paging Enable
Asked Answered
C

7

9

I have to create Grid view like Appstore iOS app. I want to do this with UICollectionView paging. I have also implemented the code but not able to scroll like that.

What I want to do is there will one image in Center and at both sides(left and right), it should show some portion of previous and next image. I have set Frame for UICollectionView is 320*320. cell size is 290*320.(cell min spacing is 10)1

Below are two links which depicts my requirement. Thanks in advance.

(This is what I want) 2

Callisto answered 19/6, 2014 at 10:1 Comment(1)
just use collectionView.isPagingEnabled = true;Cookshop
D
11

Have you tried setting the scroll direction of your UICollectionViewFlowLayout to horizontal?

[yourFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];

You'll need to enable paging on your collection view like so:

[yourCollectionView setPagingEnabled:YES];

Desiree answered 19/6, 2014 at 10:47 Comment(2)
For those using Storyboards, you can also find the checkbox Paging Enabled in Interface Builder in the Attribute Inspector of the Collection View.Desk
you also need to set the minumum spacing in yourFlowLayout to 0Larentia
B
7

I took shtefane's answer and improved on it. Enter your own cellWidth and cellPadding values.

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
                     withVelocity:(CGPoint)velocity
              targetContentOffset:(inout CGPoint *)targetContentOffset
{
    CGFloat cellWidth = self.cellWidth;
    CGFloat cellPadding = 9;

    NSInteger page = (scrollView.contentOffset.x - cellWidth / 2) / (cellWidth + cellPadding) + 1;

    if (velocity.x > 0) page++;
    if (velocity.x < 0) page--;
    page = MAX(page,0);

    CGFloat newOffset = page * (cellWidth + cellPadding);
    targetContentOffset->x = newOffset;
}
Became answered 6/2, 2016 at 1:14 Comment(0)
C
4

If you use pagining in collectionView it will scroll by one page Not one cell. You can disable pagining and implement ScrollViewDelegate

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
 {
     CGFloat pageW = 300;
    int page = scrollView.contentOffset.x / pageW;

    CGFloat newOffset =(page + ((velocity.x > 0)? 1 : -1)) * (pageW - 20);
    CGPoint target = CGPointMake(newOffset, 0);
    targetContentOffset = &target;
    NSLog(@"end Drag at %f /%i /%f",scrollView.contentOffset.x, page, velocity.x);

 }

Only one different from standart paging: If you drag fast Collection will scroll more than one cell. And don't forget to add UIScrollViewDelegate

Clemente answered 19/6, 2014 at 10:35 Comment(3)
Still same problem there.i have to set anything after setting targetContentOffset ?Callisto
Did you set pagingEnabled = NO for collectionView ?Clemente
You have your references mixed up. For this to work, your last line should be *targetContentOffset = target;.Uretic
C
3

Just use collectionView.isPagingEnabled = true;

Cookshop answered 12/7, 2018 at 5:31 Comment(0)
C
1

Here's a working swift4 version of Rickster answer:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {

    let cellWidth = 174 as CGFloat
    let cellPadding = 10 as CGFloat

    var page = (scrollView.contentOffset.x - cellWidth / 2) / (cellWidth + cellPadding) + 1

    if (velocity.x > 0) { page += 1 }
    if (velocity.x < 0) { page -= 1 }

    page = max(page,0)

    targetContentOffset.pointee.x = page * (cellWidth + cellPadding)
}
Callas answered 19/1, 2018 at 9:43 Comment(0)
C
0

Ref to Rickster's answer and I rewrite with Swift 4:

/* paging */
extension AlbumViewController {

    /* In case the user scrolls for a long swipe, the scroll view should animate to the nearest page when the scrollview decelerated. */
    override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        scrollToPage(scrollView, withVelocity: CGPoint(x:0, y:0))
    }

    override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        scrollToPage(scrollView, withVelocity: velocity)
    }

    func scrollToPage(_ scrollView: UIScrollView, withVelocity velocity: CGPoint) {
        let cellWidth: CGFloat = cellSize
        let cellPadding: CGFloat = 10

        var page: Int = Int((scrollView.contentOffset.x - cellWidth / 2) / (cellWidth + cellPadding) + 1)
        if velocity.x > 0 {
            page += 1
        }
        if velocity.x < 0 {
            page -= 1
        }
        page = max(page, 0)
        let newOffset: CGFloat = CGFloat(page) * (cellWidth + cellPadding)

        scrollView.setContentOffset(CGPoint(x:newOffset, y:0), animated: true)
    }
}
Cumae answered 19/9, 2017 at 14:59 Comment(0)
C
-1

full source is here

this supports RTL (Right to Left)

collectionView.decelerationRate = .fast


// paging
extension ViewController: UIScrollViewDelegate {
    
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        self.dragStartPoint = scrollView.contentOffset
    }
    
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        let isRTL = UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft
        let pageWidth = UIScreen.main.bounds.size.width - ViewController.left - ViewController.right + ViewController.lineSpacing
        
        if scrollView.contentOffset.x == targetContentOffset.pointee.x { // no decelerate
            if fabsf(Float(self.dragStartPoint.x - scrollView.contentOffset.x)) > 40 { // min move distance = 40
                let dragLeft = self.dragStartPoint.x < scrollView.contentOffset.x
                if dragLeft {
                    self.currentPage = isRTL ? self.currentPage - 1 : self.currentPage + 1
                } else {
                    self.currentPage = isRTL ? self.currentPage + 1 : self.currentPage - 1
                }
            }
        } else if scrollView.contentOffset.x > targetContentOffset.pointee.x {
            let maxRight = scrollView.contentSize.width - UIScreen.main.bounds.size.width
            if scrollView.contentOffset.x <= maxRight { // not right bounce
                self.currentPage = isRTL ? self.currentPage + 1 : self.currentPage - 1
            }
        } else {
            if scrollView.contentOffset.x >= 0 { // not left bounce
                self.currentPage = isRTL ? self.currentPage - 1 : self.currentPage + 1
            }
        }
        
        self.currentPage = max(0, self.currentPage)
        self.currentPage = min(self.numberOfPages - 1, self.currentPage)
        
        var offset = targetContentOffset.pointee
        if isRTL {
            offset.x = CGFloat(self.numberOfPages - self.currentPage - 1) * pageWidth
        } else {
            offset.x = CGFloat(self.currentPage) * pageWidth
        }
        targetContentOffset.pointee = offset
    }
}


Crone answered 27/7, 2020 at 8:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.