启用分页的 UICollectionView

问题描述 投票:0回答:7

我必须创建像 Appstore iOS 应用程序一样的网格视图。我想用 UICollectionView 分页来做到这一点。我也实现了代码,但无法像那样滚动。

我想要做的是在中心和两侧(左侧和右侧)都有一张图像,它应该显示上一张和下一张图像的某些部分。我已将 UICollectionView 的 Frame 设置为 320*320。单元格大小为290*320。(单元格最小间距为10)1

下面是两个描述我的要求的链接。预先感谢。

(这就是我想要的)2

ios objective-c pagination uicollectionview uiscrollview
7个回答
11
投票

您是否尝试过将 UICollectionViewFlowLayout 的滚动方向设置为水平?

[yourFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];

您需要在集合视图上启用分页,如下所示:

[yourCollectionView setPagingEnabled:YES];


7
投票

我采纳了shtefane的答案并对其进行了改进。 输入您自己的

cellWidth
cellPadding
值。

- (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;
}

4
投票

如果您在 collectionView 中使用分页,它将滚动一页而不是一个单元格。您可以禁用分页并实现 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);

 }

与标准分页只有一处不同:如果快速拖动,集合将滚动多个单元格。 并且不要忘记添加 UIScrollViewDelegate


3
投票

只需使用collectionView.isPagingEnabled = true;


1
投票

这是 Rickster 答案的 swift4 版本:

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
投票

参考 Rickster 的答案,我用 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)
    }
}

-1
投票

完整源代码在这里

这支持 RTL(从右到左)

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
    }
}


© www.soinside.com 2019 - 2024. All rights reserved.