快速实现无限轮播器

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

1.实现思路:

UI:

快速实现无限轮播器_第1张图片
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

你可能感兴趣的:(快速实现无限轮播器)