【问题标题】:UICollectionView with Paging Enable启用分页的 UICollectionView
【发布时间】:2014-08-09 19:56:51
【问题描述】:

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

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

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

(这就是我想要的)2

【问题讨论】:

  • 只使用collectionView.isPagingEnabled = true;

标签: ios objective-c uiscrollview uicollectionview paging


【解决方案1】:

完整来源是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
    }
}


【讨论】:

    【解决方案2】:

    只需使用 collectionView.isPagingEnabled = true;

    【讨论】:

      【解决方案3】:

      这是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】:

        参考 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】:

          我接受了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;
          }
          

          【讨论】:

            【解决方案6】:

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

            [yourFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];

            您需要像这样在集合视图上启用分页:

            [yourCollectionView setPagingEnabled:YES];

            【讨论】:

            • 对于那些使用 Storyboards 的人,您还可以在 Collection View 的 Attribute Inspector 中找到在 Interface Builder 中启用 Paging 复选框。
            • 您还需要将您的FlowLayout中的最小间距设置为0
            【解决方案7】:

            如果您在 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);
            
             }
            

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

            【讨论】:

            • 还有同样的问题。我必须在设置 targetContentOffset 后设置什么?
            • 您是否为 collectionView 设置了 pagingEnabled = NO ?
            • 您的参考资料混淆了。为此,您的最后一行应该是*targetContentOffset = target;
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-01-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多