iOS:UICollectionView实现无限轮播图(Swift3)

这里写图片描述
效果图

原理:给collectionView设置多组一样的数据,默认展示中间的那一组.当滚动到上一组或者下一组的时候采用无动画的方式滚动到最中间的那一组.这样就实现了视图的无限轮播.

class MCCycleView: UIView, UICollectionViewDelegate, UICollectionViewDataSource {

    private var collectionView: UICollectionView!
    private var pageControl: UIPageControl!
    private var timer: Timer?

    lazy var picArr: [UIImage] = {
        return [UIImage(named: "1")!,
                UIImage(named: "2")!,
                UIImage(named: "3")!,
                UIImage(named: "4")!,
                UIImage(named: "5")!]
    }()


    private let CycleReuseIdentifier = "CycleReuseIdentifier"
    //组数 多少组都可以最少三组
    private let MaxSections = 3

    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    private func setup() {
        //设置flowLayout属性
        let flowLayout = UICollectionViewFlowLayout()
        flowLayout.itemSize = CGSize(width: UIScreen.main.bounds.width, height: 150)
        flowLayout.minimumLineSpacing = 0
        flowLayout.minimumInteritemSpacing = 0
        flowLayout.scrollDirection = .horizontal
        collectionView = UICollectionView(frame: frame, collectionViewLayout: flowLayout)
        collectionView.isPagingEnabled = true
        collectionView.register(MCCycleCell.self, forCellWithReuseIdentifier: CycleReuseIdentifier)
        collectionView.delegate = self
        collectionView.dataSource = self
        //默认滚动到中间的那一组
        collectionView.scrollToItem(at: IndexPath(item: 0, section: MaxSections / 2), at: .left, animated: false)
        addSubview(collectionView)

        pageControl = UIPageControl()
        pageControl.numberOfPages = picArr.count
        pageControl.currentPageIndicatorTintColor = UIColor.orange
        addSubview(pageControl)

        //添加定时器
        addTimer()

        //设置collectionView和pageControl的约束
        collectionView.snp.makeConstraints { (make) in
            make.top.equalTo(self.snp.top)
            make.left.equalTo(self.snp.left)
            make.bottom.equalTo(self.snp.bottom)
            make.right.equalTo(self.snp.right)
        }

        pageControl.snp.makeConstraints { (make) in
            make.right.equalTo(self.snp.right).offset(-10)
            make.bottom.equalTo(self.snp.bottom).offset(-10)
        }
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return MaxSections
    }

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

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CycleReuseIdentifier, for: indexPath) as! MCCycleCell
        cell.img = picArr[indexPath.item]

        return cell
    }

    //在这个方法中算出当前页数
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let page = Int((scrollView.contentOffset.x + (collectionView?.bounds.width)! * 0.5) / (collectionView?.bounds.width)!)
        let currentPage = page % picArr.count
        pageControl?.currentPage = currentPage
    }

    //在开始拖拽的时候移除定时器
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        timer?.invalidate()
        timer = nil
    }

    //结束拖拽的时候重新添加定时器
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        addTimer()
    }

    //手动滑动
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        collectionView.scrollToItem(at: IndexPath(item: pageControl.currentPage, section: 1), at: .left, animated: false)
    }

    private func addTimer() {
        timer = Timer(timeInterval: 3, target: self, selector: #selector(nextImage), userInfo: nil, repeats: true)
        RunLoop.current.add(timer!, forMode: .commonModes)
    }

    @objc private func nextImage() {
        //获取当前indexPath
        let currentIndexPath = collectionView.indexPathsForVisibleItems.last!
        //获取中间那一组的indexPath
        let middleIndexPath = IndexPath(item: currentIndexPath.item, section: 1)
        //滚动到中间那一组
        collectionView.scrollToItem(at: middleIndexPath, at: .left, animated: false)

        var nextItem = middleIndexPath.item + 1
        var nextSection = middleIndexPath.section
        if nextItem == picArr.count {
            nextItem = 0
            nextSection += 1
        }
        collectionView.scrollToItem(at: IndexPath(item: nextItem, section: nextSection), at: .left, animated: true)
    }

}
class MCCycleCell: UICollectionViewCell {

    private var ImgView: UIImageView = UIImageView()

    var img: UIImage? {
        didSet {
            ImgView.image = img
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        addSubview(ImgView)
        ImgView.snp.makeConstraints { (make) in
            make.top.equalTo(self.snp.top)
            make.left.equalTo(self.snp.left)
            make.bottom.equalTo(self.snp.bottom)
            make.right.equalTo(self.snp.right)
        }
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值