Swift 3张图片轮播

写的不好 ~ swift3.0 可自定义轮播内容

/*    _       _____   __   _   _____   _   _   __    __
     | |     | ____| |  \ | | /  ___/ | | / /  \ \  / /
     | |     | |__   |   \| | | |___  | |/ /    \ \/ /
     | |     |  __|  | |\   | \___  \ | |\ \     \  /
     | |___  | |___  | | \  |  ___| | | | \ \    / /
     |_____| |_____| |_|  \_| /_____/ |_|  \_\  /_/          */


import UIKit

// ================ 代理协议 ======================
@objc protocol CycleScrollViewDelegate:NSObjectProtocol {
    //当前点击的是第几页
    @objc optional func cycleDidTapWithIndex(page:Int,cycleScrollView:CycleScrollView)
    @objc optional func cycleDidScrollPage(page:Int,cycleScrollView:CycleScrollView)
}
@objc protocol CycleScrollViewDataSource:CycleScrollViewDelegate {
    //如果是自定义的cell 必须实现下面的代理方法
    func cycleCustomView(index:Int,cycleScrollView:CycleScrollView) -> UIView
    //给自定义View 进行赋值 currentView 当前的View  data 要赋值的数据
    func cycleCustomViewConfigerData(currentView:UIView,data:Any)
}
// ============================================


//================== 枚举类型 ====================
//循环类型
enum CyScrollViewType {
    case Horizontal             //横向
    case Vertical                 //纵向
}
// ============================================


//轮播 view 使用三张图片实现  同样可以使用CollectionView 使用假象 这种用法可能有点诡异
class CycleScrollView : UIImageView,UIScrollViewDelegate {
    //当前选中的是第几个
    private var index:Int = 0
    private var imgArray:Array<Any> = []
    private var _timer:Timer?
    private var placehodeImg:UIImage?
    private var imgViews:Array<UIImageView> = []
    private var isHiddenPage:Bool = false
    private var isCustom:Bool = false
    private var scrollType:CyScrollViewType = .Horizontal    //默认是横向滚动

    //代理协议书写方式 使用 weak open var
    weak open  var lgdelegate : CycleScrollViewDelegate?
    weak open  var lgDataSource:CycleScrollViewDataSource?


//设置滚动类型
    /*
     * 上下滚动还是左右滚动
     */
    func configerScrollType(aScrollType:CyScrollViewType){
        invailTimer()
        scrollType = aScrollType
        layoutSubviews()
        index = 0
        if scrollType == .Horizontal {
            scrollView.setContentOffset(CGPoint(x: scrollView.bounds.width, y: 0), animated: true)
        }else{
            scrollView.setContentOffset(CGPoint(x: 0, y: scrollView.bounds.height), animated: true)
        }
        if imgArray.count > 1 {
            startTimer()
        }
        changeIndex()
    }

    // TODO: 设置自定义的代理
    func configerCustom(dataSource:CycleScrollViewDataSource) {
        //从新赋值代理
        invailTimer()
        //是自定义的
        isCustom = true
        lgdelegate = dataSource
        lgDataSource = dataSource
        //添加子控件
        var num:Int = 0
        for imgV in imgViews {
            //移除子控件

            imgV.subviews.forEach { (v) in
                v.removeFromSuperview()
            }
            let subV = dataSource.cycleCustomView(index: num, cycleScrollView: self)
            //添加到控件上
            imgV.addSubview(subV)
            num = num + 1
        }
        layoutSubviews()

        if imgArray.count > 1 {
            startTimer()
        }
       changeIndex()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.addSubview(scrollView)
        scrollView.delegate = self
        self.isUserInteractionEnabled  = true
        imgArray = []
        pageControl.currentPage = index
        pageControl.currentPageIndicatorTintColor = .red
        pageControl.pageIndicatorTintColor = .lightGray
        pageControl.isUserInteractionEnabled = false
        pageControl.numberOfPages = imgArray.count
        for _ in 0..<3 {
            let imgV = UIImageView()
            imgV.contentMode = .scaleAspectFill
            imgV.clipsToBounds = true
            imgViews.append(imgV)
            scrollView.addSubview(imgV)
            imgV.isUserInteractionEnabled = false
        }
        let tap = UITapGestureRecognizer(target: self, action: #selector(tapImgViewAction))
        //滚动视图上添加手势
        scrollView.addGestureRecognizer(tap)
        addSubview(pageControl)
        changeIndex()
        startTimer()
    }
    @objc func tapImgViewAction(tap:UITapGestureRecognizer){
        if tap.state == .ended {
            //点击结束
            if imgArray.count > 0 {
                lgdelegate?.cycleDidTapWithIndex?(page: index, cycleScrollView: self)
            }
        }
    }

//设置占位图
    func configerPlacehoder(placeImg:UIImage) -> Void {
        placehodeImg = placeImg
        self.image = placeImg
    }

    //设置图片数组
    func configerImgs(imgs:Array<Any>)  {
        imgArray = imgs
        pageControl.numberOfPages = imgArray.count
        invailTimer()
        if imgArray.count > 1 {
            if isHiddenPage == false {
                pageControl.isHidden = false
            }
            startTimer()
            scrollView.isScrollEnabled = true
        }else{
            scrollView.isScrollEnabled = false
            if imgArray.count == 0 {
                pageControl.isHidden = true
                self.image = placehodeImg
                self.clipsToBounds = true
                self.contentMode = .scaleAspectFit
                //图片全部滞空
                for v in imgViews {
                    v.image = nil
                }
            }else{
                self.image = nil
                pageControl.isHidden = false
            }
        }
        //修改索引值
        index = 0
        changeIndex()
    }


    private func startTimer(){
        //先销毁定时器
        invailTimer()
        //启动定时器
        _timer = Timer(timeInterval: 2, target: self, selector: #selector(onTimeAction), userInfo: nil, repeats: true)
        RunLoop.current.add(_timer!, forMode: .commonModes)
    }

    private func invailTimer(){
        _timer?.invalidate()
        _timer = nil
    }
    //定时器调用
    func onTimeAction(){
        //当前应当是第几张
        if scrollType == .Horizontal {
            scrollView.setContentOffset(CGPoint(x: scrollView.bounds.width*2, y: 0), animated: true)
        }else{
            scrollView.setContentOffset(CGPoint(x: 0, y: scrollView.bounds.height*2), animated: true)
        }
    }
    //TODO: 修改索引值 关键代码
    func changeIndex() {
        if imgArray.count <= 0 {
            scrollView.isHidden = true
            return
        }
        scrollView.isHidden = false
        pageControl.currentPage = index
        //这里没写完呢!
        let imgName1 = (index == 0) ? (imgArray.last ?? "") : imgArray[index - 1]
        let imgName2 = (imgArray.count == 1) ? (imgArray.first ?? "") : ((imgArray.count > 0) ? imgArray[index] : "")
        let imgName3 = (index == imgArray.count - 1) ? (imgArray.first ?? "") : ( (imgArray.count == 1) ? (imgArray.first ?? ""):imgArray[index + 1])
        let imgV1 :UIImageView = imgViews[0]
        let imgV2 :UIImageView = imgViews[1]
        let imgV3 :UIImageView = imgViews[2]
        if isCustom {
            //修改占位图
            self.image = nil
            lgDataSource?.cycleCustomViewConfigerData(currentView: imgV1.subviews.first!, data: imgName1)
            lgDataSource?.cycleCustomViewConfigerData(currentView: imgV2.subviews.first!, data: imgName2)
            lgDataSource?.cycleCustomViewConfigerData(currentView: imgV3.subviews.first!, data: imgName3)
            return
        }
        let str1 = imgName1 as! String
        let str2 = imgName1 as! String
        let str3 = imgName1 as! String
        //是否是不是http 开头 的
        if str1.hasPrefix("http") {
            imgV1.sd_setImage(with: URL(string: imgName1 as! String), completed: nil)
        }else{
            imgV1.image = UIImage(named: str1)
        }
        if str2.hasPrefix("http") {
            imgV2.sd_setImage(with: URL(string: imgName2 as! String), completed: nil)
        }else{
            imgV2.image = UIImage(named: str2)
        }
        if str3.hasPrefix("http") {
            imgV3.sd_setImage(with: URL(string: imgName3 as! String), completed: nil)
        }else{
            imgV3.image = UIImage(named: str3)
        }
        lgdelegate?.cycleDidScrollPage?(page: index, cycleScrollView: self)
    }
    //TODO: 滚动视图代理方法
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        invailTimer()
    }
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        if scrollType == .Horizontal {
            scrollView.contentOffset = CGPoint(x: scrollView.bounds.width, y: 0)
        }else{
            scrollView.contentOffset = CGPoint(x: 0, y: scrollView.bounds.height)
        }
        changeIndex()
        startTimer()
    }
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if scrollType == .Horizontal { //横向滚动
            if scrollView.contentOffset.x >= scrollView.bounds.width*2 {
                scrollView.contentOffset = CGPoint(x: scrollView.bounds.width, y: 0)
                index = index + 1
                if index > ( imgArray.count - 1) {//回到起点
                    index = 0
                }
                changeIndex()
            }else if scrollView.contentOffset.x <= 0{
                scrollView.contentOffset = CGPoint(x: scrollView.bounds.width, y: 0)
                index =  index - 1
                if index < 0 {
                    index = ( imgArray.count - 1)
                }
                changeIndex()
            }
        }else{
            if scrollView.contentOffset.y >= scrollView.bounds.height*2 {
                scrollView.contentOffset = CGPoint(x: 0, y: scrollView.bounds.height)
                index = index + 1 //回到起点
                if index > ( imgArray.count - 1) {
                    index = 0
                }
                changeIndex()
            }else if scrollView.contentOffset.y <= 0{
                scrollView.contentOffset = CGPoint(x: 0, y: scrollView.bounds.height)
                index =  index - 1
                if index < 0 {
                    index = ( imgArray.count - 1)
                }
                changeIndex()
            }
        }
    }
    override func layoutSubviews() {
        super.layoutSubviews()
        let arrayCount = 3
        scrollView.frame = CGRect(x: 0, y: 0, width: self.bounds.width, height: self.bounds.height)
        pageControl.frame = CGRect(x: 0, y: self.bounds.height - 12.0, width: self.bounds.width, height: 10)
        if scrollType == .Horizontal {
            let containtWidth =     self.bounds.width * CGFloat(arrayCount)
            scrollView.contentSize = CGSize(width: containtWidth, height: 0)
            scrollView.contentOffset = CGPoint(x: scrollView.bounds.width, y: 0)
            for  i   in 0..<imgViews.count {
                let v = imgViews[i]
                v.frame = CGRect(x: self.bounds.width * CGFloat(i), y: 0, width: self.bounds.width, height: self.bounds.height)
                if isCustom == true {
                    v.subviews.forEach { (subV) in    //如果是自定义View 修改自定义Viewframe
                        subV.frame = CGRect(x: 0, y: 0, width: v.bounds.width, height: bounds.height)
                    }
                }
            }
        }else{
            let containtHeight =    self.bounds.height * CGFloat(arrayCount)
            scrollView.contentSize = CGSize(width:self.bounds.width, height: containtHeight)
            scrollView.contentOffset = CGPoint(x: scrollView.bounds.height, y: 0)  //放到中间
            for  i   in 0..<imgViews.count {
                let v = imgViews[i]
                v.frame = CGRect(x: 0, y: self.bounds.height * CGFloat(i), width: self.bounds.width, height: self.bounds.height)
                if isCustom == true {  //如果是自定义View 修改自定义Viewframe
                    v.subviews.forEach { (subV) in
                        subV.frame = CGRect(x: 0, y: 0, width: v.bounds.width, height: bounds.height)
                    }
                }
            }
        }
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    //TODO: 懒加载 ====================
    lazy var scrollView = {()->UIScrollView in
        let scrollV = UIScrollView()
        scrollV.isPagingEnabled = true
        scrollV.showsVerticalScrollIndicator = false
        scrollV.showsHorizontalScrollIndicator = false
        return scrollV
    }()
    lazy var pageControl = {() -> UIPageControl in
        let page = UIPageControl()
        return page
    }()
    //TODO:  设置set 方法
    var isHiddenPageControl:Bool{
        get {
            return isHiddenPage
        }
        set {
            isHiddenPage = newValue
            pageControl.isHidden = isHiddenPage
        }
    }
}
  • 用法===============
    let cycleScrollView = CycleScrollView.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0))

        cycleScrollView.lgdelegate = self
        //cycleScrollView.configerCustom(dataSource: self)
        //是否隐藏 pageControl
        cycleScrollView.isHiddenPageControl = true
        tableHeader.addSubview(cycleScrollView)
        cyScrollView = cycleScrollView
        cycleScrollView.snp.makeConstraints { (make) in
            make.left.right.top.bottom.equalTo(0)
        }
        cycleScrollView.configerPlacehoder(placeImg: UIImage(named: "home_banner_img") ?? UIImage())
        cycleScrollView.configerScrollType(aScrollType: .Horizontal)
  • 代理协议方法
//必须实现的自定义代理方法
    func cycleCustomView(index: Int, cycleScrollView: CycleScrollView) -> UIView {
        let v = CustomCyItem()
        return v;
    }
    func cycleCustomViewConfigerData(currentView: UIView, data: Any) {
        let v:CustomCyItem = currentView as! CustomCyItem
        v.titleLable.text = data as? String
    }

    //协议方法
    func cycleDidTapWithIndex(page: Int, cycleScrollView: CycleScrollView) {
        //LGLog("点击了第" + String(page) + "页")
    }
    func cycleDidScrollPage(page: Int, cycleScrollView: CycleScrollView) {
        //LGLog("滚动到第" + String(page) + "页")
    }

猜你喜欢

转载自blog.csdn.net/weixin_34106122/article/details/87429891