【问题标题】:CollectionView move to next cell automatically swiftCollectionView 自动快速移动到下一个单元格
【发布时间】:2016-08-03 23:46:06
【问题描述】:

我正在尝试创建像 Flipkart 这样的水平滑块。我正在使用带有水平滚动和分页的 collectionView。单元格包含 imageView。我成功地手动水平滚动项目,但我希望所有这些项目都能自动和手动移动。我没有得到如何自动滚动 collectionView 的项目。请指导我这样做。

我在 viewDidAppear 中使用过这段代码:

let visibleIndexPath: NSIndexPath = self.collectionView.indexPathForCell(cell)!

self.collectionView.scrollToItemAtIndexPath(visibleIndexPath,  
atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: true)

谢谢。

编辑:

import UIKit

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

    @IBOutlet var pageControl: UIPageControl!
    @IBOutlet var collectionView: UICollectionView!
    var begin = false
    let image1 = UIImage(named: "Slide 1")
    let image2 = UIImage(named: "Slide 2")
    let image3 = UIImage(named: "Slide 1")

    var images = [UIImage]()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        images = [image1!, image2!, image3!]
        startTimer()
    }        

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        pageControl.numberOfPages = images.count
        return images.count
    }

    var cell : CollectionViewCell1!

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

      cell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell1", forIndexPath: indexPath) as! CollectionViewCell1
        cell.cell_image.image = images[indexPath.row]

        return cell
    }


    /**
     Scroll to Next Cell
     */
    func scrollToNextCell(){

        //get cell size
        let cellSize = CGSizeMake(self.view.frame.width, self.view.frame.height);

        //get current content Offset of the Collection view
        let contentOffset = collectionView.contentOffset;

            //scroll to next cell
        if begin == true
        {
            pageControl.currentPage == 0
            collectionView.scrollRectToVisible(CGRectZero, animated: true)
            begin = false
        }
        else
        {
            collectionView.scrollRectToVisible(CGRectMake(contentOffset.x + cellSize.width, contentOffset.y, cellSize.width, cellSize.height), animated: true);
        }

    }

    /**
     Invokes Timer to start Automatic Animation with repeat enabled
     */

    func startTimer() {

       NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: #selector(ViewController.scrollToNextCell), userInfo: nil, repeats: true);


    }

    func scrollViewDidEndDecelerating(scrollView: UIScrollView) {

        // If the scroll animation ended, update the page control to reflect the current page we are on

        pageControl.currentPage = Int((collectionView.contentOffset.x / collectionView.contentSize.width) * CGFloat(images.count))

        if collectionView.contentSize.width == collectionView.contentOffset.x + self.view.frame.width
        {
            begin = true

        }

    }

    func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {

        // Called when manually setting contentOffset
        scrollViewDidEndDecelerating(scrollView)

    }

}

这是我的全部代码。我无法在最后一个单元格之后转到第一个单元格。请帮帮我。

【问题讨论】:

  • 您可以使用 NSTimer 延迟 1 秒并动画到下一个单元格索引。
  • 是的.. 但我不知道如何使用 NSTimer 和 collectionView 来移动单元格。你能帮帮我吗?

标签: swift uicollectionview paging horizontal-scrolling


【解决方案1】:

这是我稍微改进的解决方案。当用户手动开始滚动时它会停止滚动,如果再次使用单元格,它会重新启动它。

private var indexCurrentCell = 0
private weak var timer: Timer?

private var items = [Item]() {
    didSet {
        collectionView.reloadData()

        indexCurrentCell()
    }
}

private func startAutoscrolling() {
    indexCurrentCell = 0
    timer?.invalidate()
    timer = Timer.scheduledTimer(withTimeInterval: 3, repeats: true) { [weak self] timer in
        guard let self = self else {
            timer.invalidate()
            return
        }

        guard !self.items.isEmpty else {
            return
        }

        if self.indexCurrentCell < self.items.count {
            let indexPath = IndexPath(item: self.indexCurrentCell, section: 0)
            self.collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
            self.indexCurrentCell += 1
        } else {
            self.indexCurrentCell = 1
            self.collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredHorizontally, animated: true)
        }
    }
    timer?.fire()
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if scrollView.isTracking {
        timer?.invalidate()
    }
}

override func awakeFromNib() {
    super.awakeFromNib()

    startAutoscrolling()
}

【讨论】:

    【解决方案2】:

    您可以使用此AutoScrollCollectionView cocoapod 在特定间隔内自动滚动来实现这一点

    就像从 AutoScrollCollectionView 子类化您的收藏视图并调用 startAutoScrolling 方法一样简单,如下所示

    self.autoScrollCollectionView.startAutoScrolling(withTimeInterval: TimeInterval(exactly: 2.0)!)
    
    self.autoScrollCollectionView.stopAutoScrolling()
    

    【讨论】:

      【解决方案3】:
      Use your pagecontrol property and scrolltoitem.
      
      func setuptimer() {
        timer = Timer.scheduledTimer(timeInterval: 3, target: self , selector: 
      #selector(startScrolling), userInfo: nil, repeats: true)
      
      }
      
      @objc func startScrolling() {
      
          if pageControl.currentPage == pageControl.numberOfPages - 1 {
              pageControl.currentPage = 0
          } else {
          pageControl.currentPage += 1
          }
          <yourCollectionView>.scrollToItem(at: IndexPath(row: pageControl.currentPage, section: 0), at: .right, animated: true)
      }
      

      【讨论】:

        【解决方案4】:

        斯威夫特 3

        这个经过测试的代码滚动到下一个单元格并返回到最后一项之后的第一项。

        func setTimer() {
             let _ = Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(MainVC.autoScroll), userInfo: nil, repeats: true)
        }
        var x = 1
        @objc func autoScroll() {
            if self.x < self.storiesForCollectionView.count {
              let indexPath = IndexPath(item: x, section: 0)
              self.collectionViewUp.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
              self.x = self.x + 1
            }else{
              self.x = 0
              self.collectionViewUp.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredHorizontally, animated: true)
            }
        }
        
        override func viewDidLoad() {
                super.viewDidLoad()
                setTimer()
            }
        

        【讨论】:

        • 其实代码应该是else { self.x = 1 self.collectionViewUp.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredHorizontally, animated: true) } 感谢您的输入。
        • 能否请您帮我将此代码用于表格视图单元格内的多个集合视图
        【解决方案5】:

        对于 Swift4

        override func viewDidLoad() {
            super.viewDidLoad()
        
            startTimer()
        }
        
        
        
        func startTimer() {
        
            let timer =  Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.scrollAutomatically), userInfo: nil, repeats: true)
        }
        
        
        @objc func scrollAutomatically(_ timer1: Timer) {
        
            if let coll  = topMenuCollection {
                for cell in coll.visibleCells {
                    let indexPath: IndexPath? = coll.indexPath(for: cell)
                    if ((indexPath?.row)! < banner.count - 1){
                        let indexPath1: IndexPath?
                        indexPath1 = IndexPath.init(row: (indexPath?.row)! + 1, section: (indexPath?.section)!)
        
                        coll.scrollToItem(at: indexPath1!, at: .right, animated: true)
                    }
                    else{
                        let indexPath1: IndexPath?
                        indexPath1 = IndexPath.init(row: 0, section: (indexPath?.section)!)
                        coll.scrollToItem(at: indexPath1!, at: .left, animated: true)
                    }
        
                }
            }
        }
        

        topMenuCollection :- 你的收藏视图

        banner.Count:- 包含集合视图的单元格数

        【讨论】:

        • 工作谢谢! : 小修改,对以前的“进行了更正
        • 看到这么多强制拆包我总是很害怕!
        【解决方案6】:

        试试这个

        var index = 0
        var inForwardDirection = true
        var timer: Timer?
        
        @objc func scrollToNextCell() {
        
            //scroll to next cell
            let items = collectionViewTable.numberOfItems(inSection: 0)
            if (items - 1) == index {
                collectionViewTable.scrollToItem(at: IndexPath(row: index, section: 0), at: UICollectionViewScrollPosition.right, animated: true)
            } else if index == 0 {
                collectionViewTable.scrollToItem(at: IndexPath(row: index, section: 0), at: UICollectionViewScrollPosition.left, animated: true)
            } else {
                collectionViewTable.scrollToItem(at: IndexPath(row: index, section: 0), at: UICollectionViewScrollPosition.centeredHorizontally, animated: true)
            }
        
            if inForwardDirection {
                if index == (items - 1) {
                    index -= 1
                    inForwardDirection = false
                } else {
                    index += 1
                }
            } else {
                if index == 0 {
                    index += 1
                    inForwardDirection = true
                } else {
                    index -= 1
                }
            }
        
        }
        
        /**
         call this method when collection view loaded
         */
        func startTimer() {
            if timer == nil {
                timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(scrollToNextCell), userInfo: nil, repeats: true);
            }
        }
        

        【讨论】:

        • 我想如果 collectionview 到达最后一张图片,那么它应该显示数组中的第一张图片
        【解决方案7】:
         /**
         Scroll to Next Cell
         */
        @objc func scrollToNextCell(){
        
        
        
            //get cell size
            let cellSize = CGSize(width:self.view.frame.size.width, height:viewForCV.frame.size.height)
        
        
            //get current content Offset of the Collection view
            let contentOffset = cvAdvertisements.contentOffset;
        
            if cvAdvertisements.contentSize.width <= cvAdvertisements.contentOffset.x + cellSize.width
            {
                cvAdvertisements.scrollRectToVisible(CGRect(x:0, y:contentOffset.y, width:cellSize.width, height:cellSize.height), animated: true);
        
            } else {
        
                cvAdvertisements.scrollRectToVisible(CGRect(x:contentOffset.x + cellSize.width, y:contentOffset.y, width:cellSize.width, height:cellSize.height), animated: true);
        
            }
        
        }
        
        /**
         Invokes Timer to start Automatic Animation with repeat enabled
         */
        func startTimer() {
        
            Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(LoginViewController.scrollToNextCell), userInfo: nil, repeats: true);
        
        }
        

        【讨论】:

          【解决方案8】:

          迅速 4:

          func scrollToNextCell(){
          
              //get cell size
              let cellSize = view.frame.size
          
              //get current content Offset of the Collection view
              let contentOffset = collectionView.contentOffset
          
              if collectionView.contentSize.width <= collectionView.contentOffset.x + cellSize.width
              {
                  let r = CGRect(x: 0, y: contentOffset.y, width: cellSize.width, height: cellSize.height)
                  collectionView.scrollRectToVisible(r, animated: true)
          
              } else {
                  let r = CGRect(x: contentOffset.x + cellSize.width, y: contentOffset.y, width: cellSize.width, height: cellSize.height)
                  collectionView.scrollRectToVisible(r, animated: true);
              }
          
          }
          

          【讨论】:

            【解决方案9】:

            我建议使用集合视图方法scrollToItem(at:at:animated:) 而不是scrollRectToVisible。它使您不必进行计算来确定要公开的矩形。您只需指定要滚动到的 indexPath。

            【讨论】:

            • 我有一个 UICollectionView,它的滚动方向是水平的。我需要自动将收集单元从右向左移动。你能帮我用 scrollToItem(at:at:animated:) 做到这一点吗? @邓肯C
            • 如何指定特定的索引路径?
            • 函数的全称是func scrollToItem(at indexPath: IndexPath, at scrollPosition: UICollectionViewScrollPosition, animated: Bool)。它需要一个 IndexPath,以及一个滚动位置。在 Xcode API 文档中查找该函数以获取更多信息。
            【解决方案10】:
            /**
             Scroll to Next Cell
             */
            func scrollToNextCell(){
            
                //get cell size
                let cellSize = CGSizeMake(self.view.frame.width, self.view.frame.height);
            
                //get current content Offset of the Collection view
                let contentOffset = collectionView.contentOffset;
            
                if collectionView.contentSize.width <= collectionView.contentOffset.x + cellSize.width
                {
                    collectionView.scrollRectToVisible(CGRectMake(0, contentOffset.y, cellSize.width, cellSize.height), animated: true);
            
                } else {
                    collectionView.scrollRectToVisible(CGRectMake(contentOffset.x + cellSize.width, contentOffset.y, cellSize.width, cellSize.height), animated: true);
            
                }
            
            }
            
            /**
             Invokes Timer to start Automatic Animation with repeat enabled
             */
            func startTimer() {
                NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: Selector("scrollToNextCell"), userInfo: nil, repeats: true);
            }
            

            【讨论】:

              【解决方案11】:

              下面是你可以尝试的代码:

                  /**
                   Scroll to Next Cell
                   */
                  func scrollToNextCell(){
              
                      //get Collection View Instance
                      let collectionView:UICollectionView;
              
                      //get cell size
                      let cellSize = CGSizeMake(self.view.frame.width, self.view.frame.height);
              
                      //get current content Offset of the Collection view
                      let contentOffset = collectionView.contentOffset;
              
                      //scroll to next cell
                      collectionView.scrollRectToVisible(CGRectMake(contentOffset.x + cellSize.width, contentOffset.y, cellSize.width, cellSize.height), animated: true);
              
              
                  }
              
                  /**
                   Invokes Timer to start Automatic Animation with repeat enabled
                   */
                  func startTimer() {
              
                      let timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("scrollToNextCell"), userInfo: nil, repeats: true);
              
              
                  }
              

              【讨论】:

              • 好的.. 谢谢。这行得通!但我希望在最后一个单元格之后它应该转到第一个单元格..
              • 你所能做的就是检查 CollectionView 的 contentSize 是否等于 contentOffset+cellSize 然后滚动到 CGRectZero
              • 我无法进入第一页.. 我按照你说的做了.. @ Babul Prabhakar
              • 如果 collectionView.contentSize.width 试试这个
              • @BabulPrabhakar 你能帮我吗我想在表格视图内的多个集合视图中实现它我该怎么做?
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2022-06-25
              • 2018-10-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多