UICollectionView with Paging Enable

前端 未结 7 1469
天命终不由人
天命终不由人 2021-02-06 09:06

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.

Wha

相关标签:
7条回答
  • 2021-02-06 09:31

    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;
    }
    
    0 讨论(0)
  • 2021-02-06 09:31

    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)
    }
    
    0 讨论(0)
  • 2021-02-06 09:31

    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
        }
    }
    
    
    
    0 讨论(0)
  • 2021-02-06 09:34

    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];

    0 讨论(0)
  • 2021-02-06 09:39

    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

    0 讨论(0)
  • 2021-02-06 09:45

    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)
        }
    }
    
    0 讨论(0)
提交回复
热议问题