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

效果图

WechatIMG31013.jpeg

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355

推荐阅读更多精彩内容