启用了分页的UICollectionView

时间:2014-06-19 10:01:24

标签: ios objective-c uiscrollview uicollectionview paging

我必须像Appstore iOS app一样创建网格视图。我想用UICollectionView分页来做这件事。我也实现了代码但不能像那样滚动。

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

以下两个链接描述了我的要求。提前谢谢。

(这就是我想要的)2

7 个答案:

答案 0 :(得分:9)

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

[yourFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];

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

[yourCollectionView setPagingEnabled:YES];

答案 1 :(得分:6)

我拿了shtefane's answer并改进了它。输入您自己的cellWidthcellPadding值。

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

答案 2 :(得分:3)

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

 }

只有一个与标准分页不同:如果你快速拖动,Collection会滚动多个单元格。 别忘了添加UIScrollViewDelegate

答案 3 :(得分: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)
}

答案 4 :(得分: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)
    }
}

答案 5 :(得分:0)

只需使用collectionView.isPagingEnabled = true;

答案 6 :(得分:0)

完整来源为here

这支持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
    }
}