快速实现无限轮播器

作者: Hayder | 来源:发表于2016-12-02 14:25 被阅读21次

    最近学习到一种快速创建轮播器的方法,感觉比以前自己实现的都要简单,记录下

    1.实现思路:

    UI:

    CycleView.xib

    使用CollcetionView来做循环滚动也没有任何的性能问题!
    1.创建一个CycleView,CycleView由一个CollectionView(与CycleView一样大)和pageCotrol两个控件组成。
    2.自定义CollectionViewCell,每个Cell大小等于CycleView的大小

    @IBOutlet weak var collectionView: UICollectionView!
    @IBOutlet weak var pageControl: UIPageControl!
    
     var titles: [String]? //数据数组,暂时放的字符串
     var timer: Timer?  //定时器
    

    调整尺寸

    override func layoutSubviews() {
        super.layoutSubviews()
        
        //获取layout属性
        let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
        layout.itemSize = collectionView.bounds.size
        layout.minimumLineSpacing = 0
        layout.minimumInteritemSpacing = 0
        layout.scrollDirection = .horizontal
        collectionView.isPagingEnabled = true
    }
    

    2.循环滚动思路:

    2.1 CollectionView的逻辑

    1.numberOfItemsInSection 方法中,将titles的个数*500,如果500嫌少,可以乘以1000。

    extension CycelView: UICollectionViewDataSource{
    
            func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        
                return (titles?.count ?? 0)*500
            }
    
            func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
                //获取当前的cell
                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: kCellID, for: indexPath) as! CycleCell
        
                //由于在numberOfItemsInSection方法中*500,所以通过对titles.count取余获得对应的index,展示对应的数据
                let index = indexPath.item % titles!.count
        
                cell.num = titles?[index]
                cell.backgroundColor = UIColor.randomColor()
        
                return cell
            }
    }
    
    2.2 PageControl的逻辑

    pageControl的逻辑主要就是在滚动的时候随着页面变化而变化。

    extension CycelView: UICollectionViewDelegate{
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        
        //获取滚动的偏移量
        let offsetx = scrollView.contentOffset.x
        
        //2.计算pageControl的currentindex
        pageControl.currentPage = Int(offsetx / scrollView.bounds.width + 0.5) % (titles?.count ?? 1)
    }
    

    }

    2.3 定时器逻辑

    主要是在创建的时候添加定时器,在开始滚动的时候移除定时器。停止移动的时候添加定时器

    extension CycelView{
    
    ///创建定时器的方法
    fileprivate func addCycleTimer(){
        
        timer = Timer(timeInterval: 2.0, target: self, selector: #selector(scrollToNext), userInfo: nil, repeats: true)
        RunLoop.main.add(timer!, forMode: .commonModes)
    }
    
    //移除定时器
    fileprivate func removeTimer(){
        
        timer?.invalidate() //从运行循环中移除
        timer = nil
    }
    
    @objc private func scrollToNext(){
        
        //1.获取当前的滚动
        let currentOffsetX = collectionView.contentOffset.x
        let offsetX = currentOffsetX + collectionView.bounds.width
        
        //2.滚动到该位置
        collectionView.setContentOffset(CGPoint(x:offsetX,y:0), animated: true)
        }
    }
    

    UICollectionViewDelegate的代理方法中,还要进行移除和添加定时器

    extension CycelView: UICollectionViewDelegate{
    
            func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        
                removeTimer()
            }
    
            func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool){
        
                addCycleTimer()
            }
    }
    
    2.4 循环滚动逻辑梳理

    在ViewController中创建完成了CycleView,将数据数组传入

    fileprivate lazy var cycleView: CycelView = {
        
        let cycleView = CycelView.cycleView()
        cycleView.frame = CGRect(x: 0, y: 20, width: kScreenW, height: kCycleViewH)
        
        return cycleView
    }()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(cycleView);
        
        cycleView.titles = ["0","1","2","3","4","5","6"]
    }
    

    在CycleView中titels接收到数据后在didSet里面进行处理

    var titles: [String]?{
        
        didSet{
    
            //1.刷新布局
            collectionView.reloadData()
            
            //2.设置pagecontrol个数
            pageControl.numberOfPages = titles?.count ?? 0
            
            //3.默认滚动到中间某一个位置
            let indexPath = IndexPath(item: (titles?.count ?? 0) * 10, section: 0)
            collectionView.scrollToItem(at: indexPath, at: .left, animated: false)
            
            //4.添加定时器 
            removeTimer() //为了安全起见,先移除定时器,再添加定时器
            
            addCycleTimer()
            
        }
    }
    

    CycleViewDemo链接: https://github.com/WzhGoSky/Demo

    相关文章

      网友评论

        本文标题:快速实现无限轮播器

        本文链接:https://www.haomeiwen.com/subject/bdsxmttx.html