Swift-UICollectionView无限轮播

Swift简单的轮播图

//
//  CycleView.swift
//

import UIKit
import SDWebImage

let CycleViewCellIdentifier: String = "CycleViewCellIdentifier"
let width = (UIScreen.main.bounds.size.width)
let height = (UIScreen.main.bounds.size.width)
let MaxSection = 100

// 协议
protocol CycleViewDelegate {
    func didSelectIndexCollectionViewCell(index: Int)->Void
}

class CycleView: UIView {
    
    //MARK: -属性列表
    
    /// 图片数组
    var imageArray: [String]?
    {
        didSet{
            pageControl.isHidden = (imageArray?.count == 1)
            pageControl.numberOfPages = (imageArray?.count)!
            collectionView.reloadData()
            startTimer()
        }
    }
    /// title数组
    var titleArray: [String]?
    {
        didSet{
            collectionView.reloadData()
            startTimer()
        }
    }
    /// 轮播时间
    var time: TimeInterval = 2
    {
        didSet{
            startTimer()
        }
    }
    
    var timer: Timer?
    var delegate: CycleViewDelegate?
    
    //MARK: -初始化
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        // 初始化UI
        setupUI(frame: frame)
    }
    override func layoutSubviews() {
        super.layoutSubviews()
        // 1.有导航控制器时,会默认在scrollview上方添加64的内边距,这里强制设置为0
        collectionView.contentInset = UIEdgeInsets.zero
        collectionView.scrollToItem(at: IndexPath(item: 0, section: MaxSection/2), at: .left, animated: false)
        
        // 2.设置subView的frame
        collectionView.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)
        pageControl.frame = CGRect(x: 0, y: 0, width: self.frame.size.width / 2, height: 15)
        pageControl.center = CGPoint(x: self.frame.size.width / 2, y: self.frame.size.height - 15)
    }
    
    //MARK: -Function
    /// 初始化UI
    private func setupUI(frame:CGRect){
        
        // 1.添加子控件
        addSubview(collectionView)
        addSubview(pageControl)
    }
    
    /// 开始定时器
    func startTimer(){
        
        //如果只有一张图片,则直接返回,不开启定时器
        if imageArray?.count == 1 {
            return
        }
        //如果定时器已开启,先停止再重新开启
        if (timer != nil) {
            endTimer()
        }
        
        timer = Timer.init(timeInterval: time, target: self, selector: #selector(nextPageView), userInfo: nil, repeats: true)
        RunLoop.current.add(timer!, forMode: RunLoopMode.commonModes)
    }
    
    /// 停止定时器
    func endTimer(){
        timer?.invalidate()
        timer = nil
    }
    
    //MARK: -进入下一页
    func nextPageView()
    {
        //获取当前indexPath
        let currentIndexPath = collectionView.indexPathsForVisibleItems.last!
        //获取中间那一组的indexPath
        let middleIndexPath = IndexPath(item: currentIndexPath.item, section: MaxSection/2)
        //滚动到中间那一组
        collectionView.scrollToItem(at: middleIndexPath, at: .left, animated: false)
        
        var nextItem = middleIndexPath.item + 1
        var nextSection = middleIndexPath.section
        if nextItem == imageArray?.count {
            nextItem = 0
            nextSection += 1
        }
        collectionView.scrollToItem(at: IndexPath(item: nextItem, section: nextSection), at: .left, animated: true)
    }
    
    //MARK: -懒加载
    fileprivate lazy var collectionView: UICollectionView = {
        print(self.frame)
        let flowLayout = CycleScrollViewFlowLayout()
        flowLayout.itemSize = CGSize(width: self.frame.size.width, height: self.frame.size.height)
        let clv = UICollectionView(frame: CGRect.zero, collectionViewLayout: flowLayout)
        clv.register(CycleViewCell.self, forCellWithReuseIdentifier: CycleViewCellIdentifier)
        clv.dataSource = self
        clv.delegate = self
        return clv
    }()
    fileprivate lazy var pageControl: UIPageControl = {
        let pc = UIPageControl()
        pc.isUserInteractionEnabled = false
        return pc
    }()
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

//MARK: -
extension CycleView: UICollectionViewDelegate,UICollectionViewDataSource
{
    //MARK: -UICollectionViewDataSource
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return MaxSection
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        
        return imageArray?.count ?? 0
    }
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CycleViewCellIdentifier, for: indexPath) as! CycleViewCell
        cell.dict = ["labelText":titleArray?.count == nil  ? "labelText" : (titleArray?[indexPath.row])!,
                     "imageStr" :(imageArray?[indexPath.row])!]
        return cell
    }
    
    
    //MARK: -UICollectionViewDelegate
    // 点击轮播图片
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        self.delegate?.didSelectIndexCollectionViewCell(index: indexPath.row)
    }
    
    
    //MARK: -UIScrollViewDelegate
    // 停止拖拽的时候开始执行
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        endTimer()
    }
    
    // 停止拖拽的时候开始执行
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        startTimer()
    }
    
    // 手指离开减速停止的时候开始执行
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        //暂不做处理
    }
    
    //在这个方法中算出当前页数
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let page = Int((scrollView.contentOffset.x + (collectionView.bounds.width) * 0.5) / (collectionView.bounds.width))
        let currentPage = page % (imageArray?.count)!
        pageControl.currentPage = currentPage
        
        //起始位置和最终位置的切换
        if scrollView.contentOffset.x >= (CGFloat)((imageArray?.count)! * MaxSection - 3) * width || scrollView.contentOffset.x <= 2{
            collectionView.scrollToItem(at: IndexPath(item: pageControl.currentPage, section: MaxSection/2), at: .left, animated: false)
        }
    }
}

//MARK: -
class CycleScrollViewFlowLayout:UICollectionViewFlowLayout
{
    override func prepare() {
        
        // 1.设置layout布局
        minimumInteritemSpacing = 0
        minimumLineSpacing = 0
        scrollDirection = UICollectionViewScrollDirection.horizontal
        
        // 2.设置collectionView的属性
        collectionView?.isPagingEnabled = true
        collectionView?.showsHorizontalScrollIndicator = false
        collectionView?.showsVerticalScrollIndicator = false
    }
}

//MARK: -
let CycleViewCellBottomViewHeight: CGFloat = 30
let CycleViewCellMargin: CGFloat = 10

class CycleViewCell: UICollectionViewCell {
    
    var dict: [String:String]?
    {
        didSet{
            iconImageView.sd_setImage(with: NSURL(string: (dict!["imageStr"])!) as URL?, placeholderImage: UIImage(named: "banner"))
            
            if dict?["labelText"] == "labelText" {
                titleLabel.isHidden = true
                bottomView.isHidden = true
            }
            else
            {
                titleLabel.text = dict?["labelText"]
                titleLabel.isHidden = false
                bottomView.isHidden = false
            }
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        // 1.添加子控件
        contentView.addSubview(iconImageView)
        iconImageView.addSubview(bottomView)
        bottomView.addSubview(titleLabel)
        
        // 2.布局子控件
        iconImageView.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)
        bottomView.frame = CGRect(x: 0, y: frame.size.height - CycleViewCellBottomViewHeight, width: height, height: CycleViewCellBottomViewHeight)
        titleLabel.frame = CGRect(x: CycleViewCellMargin, y: 0, width: height - 2*CycleViewCellMargin, height: CycleViewCellBottomViewHeight)
    }
    
    //MARK: -懒加载
    private lazy var iconImageView: UIImageView = {
        let img = UIImageView()
        return img
    }()
    private lazy var bottomView: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.5)
        return view
    }()
    private lazy var titleLabel: UILabel = {
        let label = UILabel()
        label.textColor = UIColor.white
        label.font = UIFont.systemFont(ofSize: 14)
        return label
    }()
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

效果图

Swift-UICollectionView无限轮播_第1张图片
WechatIMG31013.jpeg

如果有什么问题请大家指正,谢谢!

推荐轮播1 - SDCycleScrollView
推荐轮播2 - XRCarouselView
推荐轮播2 - 创建轮播图的四种思路

你可能感兴趣的:(Swift-UICollectionView无限轮播)