【问题标题】:Making a UICollectionView continuously scroll使 UICollectionView 连续滚动
【发布时间】:2016-06-26 14:26:06
【问题描述】:

我有一个游戏,我需要让一块字母板不断滚动,并循环遍历一组数据 (A, D, X, S, R, P, F, G, H, Y, W, M)(像这样:https://www.youtube.com/watch?v=z3rO8TbkS-U&feature=youtu.be)。当用户点击一个字母时,该字母需要从板上移除。我不能让板子停止滚动,它需要不断滚动。

我不确定该怎么做。我一直在尝试使用 UICollectionView 执行此操作,但我不确定如何执行此操作。

任何帮助将不胜感激!谢谢:)

【问题讨论】:

    标签: ios uiscrollview uicollectionview uikit


    【解决方案1】:

    我在StableCollectionViewLayout 中实现了这个。

    它基于 UICollectionViewLayout 子类使用方法

    override open func prepare(forCollectionViewUpdates updateItems: [UICollectionViewUpdateItem]) {
    super.prepare(forCollectionViewUpdates: updateItems)
    
    // there is possible to calculate a content offset the difference
    // with the help layout attributes for each updated item or only visible items
        self.offset = calculate(...)
    }
    
    override open func finalizeCollectionViewUpdates() {
        super.finalizeCollectionViewUpdates()
        self.offset = nil
    }
    
    override open func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {
        // there is necessary to add difference to/instead proposedContentOffset
        if let offset = self.offset {
           return offset
        }
        return proposedContentOffset
    }
    

    【讨论】:

      【解决方案2】:

      可以通过一种非常简单的技术来实现集合视图中的无限滚动。

      注意:据报道,此技术不适用于 iOS 12。为了获得更好的结果,我在解释此方法后添加了一种新方法。

      1) 在集合视图的 numberOfItemsInSection 委托方法中返回一个巨大的数字。

      func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int{
      
           return Int(INT_MAX)
      }
      

      2) 将集合视图中的项目数与您用来获取重复数据的数组或字典的数量相模。

      func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{
      
           let cell = collectionView.dequeueReusableCell(withReuseIdentifier: 
                      cellIdentifier, for: indexPath)
           let displayText = indexPath.row % 10
           cell.displayLabel.text = String(displayText)
           return cell
      
      }
      

      这里我没有数据,因此我使用 indexPath.row 在我的标签中显示行号。

      假设我有 10 个数据要显示,并且目前我有大量的项目,所以我对当前项目的编号取模 10。您可以使用数组或字典的计数对行进行取模,如下所示:

      let displayText = aryData.count % 10
      

      现在解释另一种适用于任何 iOS 并能提供更好输出的技术:

      1)将数组中的项目数乘以2,然后我们需要使用collectionview的内容偏移量。我将在下面发布有关如何处理此技术的代码。

      func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
              return aryData.count * 2
          }
      
          func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
              let cell = colView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! colViewCell
      
              var index = indexPath.item
              if index > aryData.count - 1 {
                  index -= aryData.count
              }
              cell.displayLabel.text = aryData[index % aryData.count]
              return cell
          }
      
          func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
      
              // if collection view scrolls vertically, use offset.y else comment below code
              var offset = collectionView.contentOffset
              let height = collectionView.contentSize.height
              if offset.y < height/4 {
                  offset.y += height/2
                  collectionView.setContentOffset(offset, animated: false)
              } else if offset.y > height/4 * 3 {
                  offset.y -= height/2
                  collectionView.setContentOffset(offset, animated: false)
              }
      
              // if collection view scrolls horizontally, use offset.x else comment below line of code
              // In my case the collectionview scrolls vertically this I am commenting below line of code
              //        let width = collectionView.contentSize.width
              //        if offset.x < width/4 {
              //            offset.x += width/2
              //            collectionView.setContentOffset(offset, animated: false)
              //        } else if offset.x > width/4 * 3 {
              //            offset.x -= width/2
              //            collectionView.setContentOffset(offset, animated: false)
              //        }
          }
      

      下面是这段代码的输出。

      希望对你有帮助:)

      【讨论】:

      • 谢谢!关于如何让 collectionView 在用户不滑动的情况下自动滚动的任何想法?
      • 如果您想在不让用户滑动的情况下执行滑动操作,那么我想您应该使用 NSTimer 创建一个计时器并调用您在用户滑动时调用的方法。如果您对使用 NSTimer 有疑问,请告诉我。我可能错了,但这可能有用:)
      • 该链接不再有效。这就是为什么您应该始终将解决方案粘贴到您的答案中 - 而不仅仅是链接。
      • 我不建议在 iOS 11 中使用这种技术(可能从 10.3.1 开始)。因为 UICollectionView 在内部 malloc 的一些数据在 UICollectionViewData _updateItemCounts 中导致崩溃(对于 1 亿个项目在一个部分中生成大约 780MB 的内存)
      • 在 iOS 12+ 上,Int.max 和 Int(INT_MAX) 在模拟器和设备中都会崩溃。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-14
      • 1970-01-01
      • 2023-03-21
      相关资源
      最近更新 更多