swift3 循环滚动视图 自适应横竖屏 reload数据源

 一句话创建banner图,可时时刷新

用到了 SnapKit、SDWebImage两个第三方库

实现步骤----------------------------------------------------

import UIKit

typealias BtnBlock = (Int) -> Void

//ImagesBlock

typealias ImagesBlock = () -> [String]

class CycleView: UIView,UIScrollViewDelegate {

    

    //MARK: - 私有属性

    private var btnBlock:BtnBlock?  //block

    private var imageBlock:ImagesBlock?

    

    private var scrollView: UIScrollView?

    private var pageControl: UIPageControl?

    private var images:[UIImage]?

    private var imageStrs:[String]?

    private var timer: Timer?

    private var currentPage = 0 {

        didSet {

            pageControl?.currentPage = currentPage

            resetImageViewSource()

        }

    }

    //MARK: - 给外部调用的属性

    var rollingTime: TimeInterval = 2.0   //滚动一页的时间

    var rollingEnable: Bool = false {             //是否自动滚动

        willSet {

            if newValue != rollingEnable {

                if newValue {

                    startTimer()

                } else {

                    stopTimer()

                }

            }

        }

    }

    //MARK: -  刷新数据

    public func reloadCyc(){

        imageStrs = imageBlock?()

        pageControl?.numberOfPages = (imageStrs?.count)!

        

        if imageStrs?.count != 0{

            currentPage = 0

            if imageStrs?.count == 1{

                stopTimer()

                scrollView?.isScrollEnabled = false

            }else{

                startTimer()

                scrollView?.isScrollEnabled = true

            }

        }else{

            stopTimer()

            scrollView?.isScrollEnabled = false

            for i in 0..<3 {

                let img = scrollView?.subviews[i] as! UIImageView

                img.image = nil

            }

        }

        

    }

    //MAKR:- 暴露创建对象方法

    /// 获取到一个滚动视图

    ///

    /// - parameter imageSourceBlock: image数据block

    /// - parameter btnBlk:           scroview点击block

    ///

    /// - returns: CycleView对象

    static func showCycView(imageSourceBlock:ImagesBlock?,btnBlk:BtnBlock?) -> CycleView {

        let cycView = CycleView()

        cycView.showCycView(imageSourceBlock: imageSourceBlock, btnBlk: btnBlk)

        return cycView

    }

    //私有对象方法

   private func showCycView(imageSourceBlock:ImagesBlock?,btnBlk:BtnBlock?) -> Void{

        imageBlock = imageSourceBlock

        btnBlock = btnBlk

        setUI()

        self.reloadCyc()

        startTimer()

    }

    //创建UI

    private func setUI(){

        scrollView = UIScrollView()

        self.addSubview(scrollView!)

        scrollView?.backgroundColor = UIColor.gray

        scrollView?.snp.makeConstraints({ (make) in

            make.top.left.bottom.right.equalToSuperview()

        })

        

        scrollView?.showsHorizontalScrollIndicator = false

        scrollView?.showsVerticalScrollIndicator = false

        scrollView?.isPagingEnabled = true

        scrollView?.bounces = false

        scrollView?.delegate = self

        

        scrollView?.addSubview(UIImageView())

        scrollView?.addSubview(UIImageView())

        scrollView?.addSubview(UIImageView())

        

        let tap = UITapGestureRecognizer(target: self, action: #selector(self.tapAction))

        scrollView?.addGestureRecognizer(tap)

        

        pageControl?.isEnabled = false

        pageControl = UIPageControl()

        pageControl?.currentPage = 0

        pageControl?.isUserInteractionEnabled = false

        pageControl?.currentPageIndicatorTintColor = UIColor.green

        pageControl?.pageIndicatorTintColor = UIColor.gray

        self.addSubview(pageControl!)

        pageControl?.snp.makeConstraints({ (make) in

            make.left.equalToSuperview().offset(10)

            make.right.equalToSuperview().offset(-10)

            make.bottom.equalToSuperview().offset(-20)

            make.height.equalTo(30)

        })

    }

    //MARK:- 自动滚动

    //开始滚动

    private func startTimer() {

        if timer==nil {

            timer = Timer.scheduledTimer(timeInterval: rollingTime, target: self, selector: #selector(scrollForTime(time:)), userInfo: nil, repeats: true)

        }

    }

    //停止滚动

    private func stopTimer() {

        if(timer != nil){

        timer!.invalidate()

        timer = nil

        }

    }

    //滚动事件

    func scrollForTime(time:Timer) -> Void {

        scrollView?.setContentOffset(CGPoint(x: self.frame.size.width * 2, y: 0), animated: true)

    }

    

    //MARK:- 适配scroview及image

    override func layoutSubviews() {

        super.layoutSubviews()

        

        scrollView?.contentSize = CGSize( self.frame.size.width * 3, height: self.frame.size.height)

        scrollView?.setContentOffset(CGPoint(x: self.frame.size.width * 2, y: 0), animated: false)

        

        for i in 0..<3 {

            let img = scrollView?.subviews[i] as! UIImageView

            img.contentMode = .scaleAspectFit

            img.clipsToBounds = true

            img.frame = CGRect(x: CGFloat(i) * (scrollView?.frame.size.width)!, y: 0, (scrollView?.frame.size.width)!, height: (scrollView?.frame.size.height)!)

        }

    }

    

    //MARK:-每当滚动后重新设置各个imageView的图片

    func resetImageViewSource() {

        let placeholderImage = UIImage(named: "placeholder.png")

        

        let leftImageView = scrollView?.subviews[0] as! UIImageView

        let middleImageView = scrollView?.subviews[1] as! UIImageView

        let rightImageView = scrollView?.subviews[2] as! UIImageView

        //当前显示的是第一张图片

        if currentPage == 0 {

            

            leftImageView.sd_setImage(with: URL.init(string: (imageStrs?.last)!), placeholderImage: placeholderImage)

            

            middleImageView.sd_setImage(with: URL.init(string: (imageStrs?[currentPage])!), placeholderImage: placeholderImage)

            

            let rightImageIndex = (imageStrs?.count)!>1 ? 1 : 0 //保护

            rightImageView.sd_setImage(with: URL.init(string: (imageStrs?[rightImageIndex])!), placeholderImage: placeholderImage)

            

        }//当前显示的是最后一张图片

        else if currentPage == (imageStrs?.count)! - 1 {

            

            leftImageView.sd_setImage(with: URL.init(string: (imageStrs?[currentPage-1])!), placeholderImage: placeholderImage)

            

            middleImageView.sd_setImage(with: URL.init(string: (imageStrs?[currentPage])!), placeholderImage: placeholderImage)

            

            rightImageView.sd_setImage(with: URL.init(string: (imageStrs?[0])!), placeholderImage: placeholderImage)

            

        }//其他情况

        else{

            

            leftImageView.sd_setImage(with: URL.init(string: (imageStrs?[currentPage-1])!), placeholderImage: placeholderImage)

            

            middleImageView.sd_setImage(with: URL.init(string: (imageStrs?[currentPage])!), placeholderImage: placeholderImage)

            

            rightImageView.sd_setImage(with: URL.init(string: (imageStrs?[currentPage+1])!), placeholderImage: placeholderImage)

        }

        

        scrollView?.setContentOffset(CGPoint(x: self.frame.size.width, y: 0), animated: false)

    }

    

    //MARK: - scrollViewDelegate

    //setContentOffset的动画完成后会调用,使currentPage+1

    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {

        if imageStrs?.count != 0{

            currentPage = (currentPage+1)%(imageStrs?.count)!

        }

    }

    //拖动scrollView时会停止自动滚动

    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {

        if rollingEnable {

            stopTimer()

        }

    }

    //停止拖动后会重新开始自动滚动

    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {

        if rollingEnable {

            startTimer()

        }

        scrollView.isScrollEnabled = false

    }

    //拖动scrollView时当减速动画结束时调用

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

        scrollView.isScrollEnabled = true

        

        if imageStrs?.count != 0{

            if scrollView.contentOffset.x == 0 {                                    //向前滑动

                if currentPage == 0 {

                    currentPage = (imageStrs?.count)!-1

                } else {

                    currentPage -= 1

                }

            } else if scrollView.contentOffset.x == 2 * self.frame.size.width {     //向后滑动

                currentPage = (currentPage+1)%(imageStrs?.count)!

            }

        }

    }

    

    //MARK:- 点击图片回调事件

    func tapAction() {

        if imageStrs?.count != 0{

        btnBlock?(currentPage)

        }

    }

}

调用方法----------------------

import UIKit

import SnapKit

import SDWebImage

class ViewController: UIViewController {

    var imageStrs = [String]()

    var cyc : CycleView?

    override func viewDidLoad() {

        super.viewDidLoad()

        self.automaticallyAdjustsScrollViewInsets = false

        setUI()

        

    }

    

    func setUI(){

        cyc = CycleView.showCycView(imageSourceBlock: { () -> [String] in

            return self.imageStrs //返回图片url,若要支持本地图片,自行修改

        }) { (tag) in

            print("tag:(tag)")//图片点击回调

        }

        

        self.view.addSubview(cyc!)

        

        cyc?.rollingTime = 4

        cyc?.snp.makeConstraints { (make) in

            make.left.right.equalToSuperview().offset(0)

            make.top.equalToSuperview().offset(20)

            make.height.equalTo(230)

        }

        

        

        let btn = UIButton(type: UIButtonType.system)

        btn.setTitle("增加image", for: UIControlState.normal)

        self.view.addSubview(btn)

        btn.tag = 1

        

        btn.addTarget(self, action: #selector(btnAction(btn:)), for: UIControlEvents.touchUpInside)

        btn.snp.makeConstraints { (make) in

            make.center.equalToSuperview()

            make.width.equalTo(100)

            make.height.equalTo(30)

        }

        

        let btn2 = UIButton(type: UIButtonType.system)

        btn2.setTitle("减少image", for: UIControlState.normal)

        self.view.addSubview(btn2)

        btn2.tag = 2

        btn2.addTarget(self, action: #selector(btnAction(btn:)), for: UIControlEvents.touchUpInside)

        btn2.snp.makeConstraints { (make) in

            make.centerX.equalTo(btn.snp.centerX)

            make.centerY.equalTo(btn.snp.centerY).offset(100)

            make.width.equalTo(100)

            make.height.equalTo(30)

        }

    }

    var count = 0

    func btnAction(btn:UIButton){

        let str1 = "http://d.hiphotos.baidu.com/image/pic/item/f9dcd100baa1cd11c1c35727bb12c8fcc3ce2dbb.jpg"

        let str2 = "http://c.hiphotos.baidu.com/image/pic/item/6c224f4a20a4462323289f659a22720e0df3d7d2.jpg"

        let str3 = "http://d.hiphotos.baidu.com/image/pic/item/7dd98d1001e939014acbb73979ec54e737d196ef.jpg"

        let str4 = "http://i.zeze.com/attachment/forum/201502/09/122834pcd2q5l5dcnd4nqc.jpg"

        let str5 = "http://img0.imgtn.bdimg.com/it/u=2176846966,1717026392&fm=21&gp=0.jpg"

        let str6 = "http://b.hiphotos.baidu.com/zhidao/wh=450,600/sign=457d1fcc2c2eb938ec3872f6e052a903/21a4462309f7905289b85b130ff3d7ca7bcbd573.jpg"

        let str7 = "http://img2.imgtn.bdimg.com/it/u=2553369102,2423460114&fm=21&gp=0.jpg"

        let str8 = "http://img0.imgtn.bdimg.com/it/u=3230797900,10373402&fm=21&gp=0.jpg"

        let str9 = "http://img4.imgtn.bdimg.com/it/u=1432393253,809810063&fm=21&gp=0.jpg"

        

        let arr = [str1,str2,str3,str4,str5,str6,str7,str8,str9]

        

        if btn.tag == 1{

            if count >= arr.count{

                imageStrs.removeAll()

                count = 0;

            }

            imageStrs.append(arr[count])

            cyc?.reloadCyc()

            count += 1

        }else{

            if imageStrs.count != 0{

            imageStrs.removeLast()

            cyc?.reloadCyc()

            count -= 1

            }else{

                count = 0

            }

        }

    }

       override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        

    }

}

demo下载地址 

群号:186052819
原文地址:https://www.cnblogs.com/zuidap/p/5923912.html