【问题标题】:How to programmatically scroll through a collection view?如何以编程方式滚动浏览集合视图?
【发布时间】:2016-08-08 13:05:18
【问题描述】:

我的视图中有一个集合视图。在单元格中是图像视图,它有一个部分。

我现在想以编程方式滚动图像。我希望动画无休止地发生,所以它在到达第 10 项后从第 1 项开始。

如果您提供一些方法来放置动画(例如以编程方式从右侧滑入后单元格变大),这也会很有帮助。

【问题讨论】:

    标签: ios swift animation uicollectionview


    【解决方案1】:

    有两种方法可以帮助您实现这一目标:

    func scrollToItemAtIndexPath(indexPath: NSIndexPath,
            atScrollPosition scrollPosition: UICollectionViewScrollPosition,
                    animated animated: Bool)
    

    func setContentOffset(contentOffset: CGPoint,
             animated animated: Bool)
    

    两者都在UICollectionView,所以你可以使用任何看起来更方便的东西。然而,为此创建自定义动画更加困难。 this answer 是一个快速解决方案,具体取决于您的需要。

    Swift 4、iOS 11:

    // UICollectionView method
    func scrollToItem(at indexPath: IndexPath, 
                      at scrollPosition: UICollectionViewScrollPosition,  
                      animated: Bool)
    
    // UIScrollView method
    func setContentOffset(_ contentOffset: CGPoint, animated: Bool)
    

    【讨论】:

    • 这两种方法都可以以滚动的方式工作,但您有一个想法,让它从第 1 项滚动到第 2 项、第 3 项、第 4 项,然后从第 10 项滚动到第 1 项,并且均匀加速不断发生的运动。我的意思是当你用手指滚动时发生的事情是以编程方式发生的。
    • 然后您可以使用NSTimer 执行重复任务并调用setContentOffset,每次调用后值递增。
    • 完成滚动到某个项目后是否有可能触发计时器?某事。喜欢等待完成然后开火?
    • 我认为这是不可能的,但是如果你在没有动画的情况下滚动并且计时器循环非常小并且你增加的值很小,它应该看起来很平滑。
    • 所以我需要测量执行滚动所需的时间。
    【解决方案2】:

    斯威夫特 5

    基于Mr.Bean'sanswer,这是使用 UICollectionView 扩展的优雅方式:

    extension UICollectionView {
        func scrollToNextItem() {
            let contentOffset = CGFloat(floor(self.contentOffset.x + self.bounds.size.width))
            self.moveToFrame(contentOffset: contentOffset)
        }
    
        func scrollToPreviousItem() {
            let contentOffset = CGFloat(floor(self.contentOffset.x - self.bounds.size.width))
            self.moveToFrame(contentOffset: contentOffset)
        }
    
        func moveToFrame(contentOffset : CGFloat) {
            self.setContentOffset(CGPoint(x: contentOffset, y: self.contentOffset.y), animated: true)
        }
    }
    

    现在您可以在任何地方使用它:

    collectionView.scrollToNextItem()
    collectionView.scrollToPreviousItem()
    

    【讨论】:

    • 应该在 ScrollToNextItem 之前检查 guard contentOffset <= self.contentSize.width - self.bounds.size.width else { return }
    【解决方案3】:

    到目前为止,这是我遇到的最好的方法,诀窍是滚动到包含下一个对象的框架。请参考代码

    /* -------------- display previous friends action ----------------*/
    @IBAction func actionPreviousFriends(_ sender: Any) {
    
        let collectionBounds = self.collectionView.bounds
        let contentOffset = CGFloat(floor(self.collectionView.contentOffset.x - collectionBounds.size.width))
        self.moveToFrame(contentOffset: contentOffset)
    }
    
    /* -------------- display next friends action ----------------*/
    @IBAction func actionNextFriends(_ sender: Any) {
    
        let collectionBounds = self.collectionView.bounds
        let contentOffset = CGFloat(floor(self.collectionView.contentOffset.x + collectionBounds.size.width))
        self.moveToFrame(contentOffset: contentOffset)
    }
    
    func moveToFrame(contentOffset : CGFloat) {
    
        let frame: CGRect = CGRect(x : contentOffset ,y : self.collectionView.contentOffset.y ,width : self.collectionView.frame.width,height : self.collectionView.frame.height)
        self.collectionView.scrollRectToVisible(frame, animated: true)
    }
    

    【讨论】:

      【解决方案4】:

      你可以使用这个 UICollectionView 扩展(Swift 4.2

              extension UICollectionView {
      
              func scrollToNextItem() {
                  let scrollOffset = CGFloat(floor(self.contentOffset.x + self.bounds.size.width))
                  self.scrollToFrame(scrollOffset: scrollOffset)
              }
      
              func scrollToPreviousItem() {
                  let scrollOffset = CGFloat(floor(self.contentOffset.x - self.bounds.size.width))
                  self.scrollToFrame(scrollOffset: scrollOffset)
              }
      
              func scrollToFrame(scrollOffset : CGFloat) {
                  guard scrollOffset <= self.contentSize.width - self.bounds.size.width else { return }
                  guard scrollOffset >= 0 else { return }
                  self.setContentOffset(CGPoint(x: scrollOffset, y: self.contentOffset.y), animated: true)
              }
          }
      

      而且用法会是这样的

      yourCollectionView.scrollToNextItem()
      yourCollectionView.scrollToPreviousItem()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-12-06
        • 1970-01-01
        • 2011-09-22
        • 1970-01-01
        • 2014-09-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多