Swift 轮播图

作者: 单抽律化娜 | 来源:发表于2019-12-10 11:04 被阅读0次
    /// 代理方法
    @objc protocol CycleScrollViewDelegate: NSObjectProtocol {
        
        /// 有多少图片
        func cycleImageCount() -> Int
        
        /// 图片和当前下标
        func cycleImageView(_ imageView: UIImageView, index: Int)
        
        /// 点击图片下标
        @objc optional func cycleImageViewClick(_ index: Int)
    }
    
    /// 轮播图
    class CycleScrollView: UIView, UIScrollViewDelegate {
    
        /// 图片数组
        private var imageViews = [UIImageView(), UIImageView(), UIImageView()]
        
        /// 滚动页面
        private var scrollView: UIScrollView!
        
        /// 图片个数
        private var imageCount: Int = 0
        
        /// 计时器
        private var timer: Timer? = nil
        
        /// 存储下标
        private var index: Int = 0
        
        /// 当前显示下标
        public var currentIndex: Int {
            get {
                return index
            }
            set {
                index = min(newValue, imageCount)
                updateImage()
            }
        }
        
        /// 是否滚动
        public var rollingEnable: Bool = false {
            willSet {
                newValue ? startTimer() : stopTimer()
            }
        }
        
        /// 滚动间隔
        public var duration: TimeInterval = 3.0
        
        /// 代理
        public weak var delegate: CycleScrollViewDelegate? {
            didSet {
                if let delegate = delegate {
                    imageCount = delegate.cycleImageCount()
                    scrollView.isScrollEnabled = imageCount > 1
                }
            }
        }
        
        /// 初始化
        override init(frame: CGRect) {
            super.init(frame: frame)
            
            scrollView = UIScrollView()
            scrollView.isPagingEnabled = true
            scrollView.bounces = false 
            scrollView.showsHorizontalScrollIndicator = false
            scrollView.showsVerticalScrollIndicator = false
            scrollView.delegate = self
            addSubview(scrollView)
            
            for item in imageViews {
                scrollView.addSubview(item)
            }
            
            addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap(_:))))
        }
        
        /// 设置
        override func layoutSubviews() {
            super.layoutSubviews()
            if (imageViews[0].frame == .zero) {
                let width = frame.width, height = frame.height
                scrollView.frame = CGRect(x: 0, y: 0, width: width, height: height)
                scrollView.contentSize = CGSize(width: width * 3, height: height)
                for (i, obj) in imageViews.enumerated() {
                    obj.frame = CGRect(x: CGFloat(i) * width, y: 0, width: width, height: height)
                }
                currentIndex = index
            }
        }
        
        /// 点击
        @objc private func tap(_ gesture: UITapGestureRecognizer) {
            delegate?.cycleImageViewClick?(currentIndex)
        }
        
        /// 更新图片
        private func updateImage() {
            if (imageCount < 2) {
                delegate?.cycleImageView(imageViews[1], index: index)
            } else {
                for (i, index) in [getLast(currentIndex), currentIndex, getNext(currentIndex)].enumerated() {
                    delegate?.cycleImageView(imageViews[i], index: index)
                }
            }
            scrollView.contentOffset.x = frame.width
        }
        
        /// 开始计时器
        private func startTimer() {
            if (imageCount < 2) {
                return
            }
            timer = Timer.scheduledTimer(timeInterval: duration, target: self, selector: #selector(rolling), userInfo: nil, repeats: true)
            RunLoop.current.add(timer!, forMode: .commonModes)
        }
        
        /// 暂停计时器
        private func stopTimer() {
            if (imageCount < 2) {
                return
            }
            timer?.invalidate()
            timer = nil
        }
        
        /// 计时方法
        @objc private func rolling() {
            scrollView.setContentOffset(CGPoint(x: frame.width * 2, y: 0), animated: true)
        }
        
        /// scrollView开始拖拽
        func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
            if rollingEnable {
                stopTimer()
            }
        }
        
        /// scrollView结束拖拽
        func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
            if rollingEnable {
                startTimer()
            }
        }
        
        /// scrollView滚动
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            if scrollView.contentOffset.x <= 0 {
                currentIndex = getLast(currentIndex)
            } else if scrollView.contentOffset.x >= 2 * scrollView.frame.width {
                currentIndex = getNext(currentIndex)
            }
            /// 修复automaticallyAdjustsScrollViewInsets问题
            if (scrollView.contentOffset.y != 0) {
                scrollView.contentOffset.y = 0
            }
        }
        
        /// 获取下一页页码
        private func getNext(_ current: Int) -> Int {
            let count = imageCount - 1
            if (count < 1) {
                return 0
            }
            return current + 1 > count ? 0 : current + 1
        }
        
        /// 获取上一页页码
        private func getLast(_ current: Int) -> Int {
            let count = imageCount - 1
            if (count < 1) {
                return 0
            }
            return current - 1 < 0 ? count : current - 1
        }
        
        /// 如果有计时器存在,必须停止计时器才能释放
        override func removeFromSuperview() {
            super.removeFromSuperview()
            stopTimer()
        }
        
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    
    import UIKit
    
    class ViewController: UIViewController, CycleScrollViewDelegate {
        
        var images: [String] = ["image1.jpeg", "image2.jpeg", "image3.jpeg", "image4.jpeg"]
        
        var cycleView: CycleScrollView!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
            cycleView = CycleScrollView(frame: CGRect.init(x: 0, y: 0, width: view.frame.width, height: 200))
            cycleView.delegate = self 
            cycleView.rollingEnable = true
            view.addSubview(cycleView)
        }
    
        /// 设置图片数量
        func cycleImageCount() -> Int {
            return images.count
        }
        
        /// 设置显示的图片
        func cycleImageView(_ imageView: UIImageView, index: Int) {
            imageView.image = UIImage(named: images[index])
        }
        
        /// 点击图片,返回下标
        func cycleImageViewClick(_ index: Int) {
            print(index)
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    }
    

    相关文章

      网友评论

        本文标题:Swift 轮播图

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