美文网首页
Swift-UICollectionView无限轮播

Swift-UICollectionView无限轮播

作者: Simple_Code | 来源:发表于2017-08-29 11:16 被阅读38次

    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")
        }
    }
    
    

    效果图

    WechatIMG31013.jpeg

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

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

    相关文章

      网友评论

          本文标题:Swift-UICollectionView无限轮播

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