iOS 自定义滑动条

2020-06-19  本文已影响0人  gaookey
import UIKit

class SliderView: UIView {
    
    private let sliderCircleSize: CGFloat = 20
    private let sliderValueSize: CGFloat = 30
    private let topSliderHeight: CGFloat = 9
    private let bottomSliderHeight: CGFloat = 5
    
    var touchesMovedHandler: ((_ progress: CGFloat, _ state: UIGestureRecognizer.State) -> ())?
    
    var progress: CGFloat = 0 {
        willSet {
            topSlider.snp.updateConstraints { (make) in
                make.width.equalTo(newValue * (bounds.size.width - sliderCircleSize / 2))
            }
        }
    }
    
    lazy var sliderValue: UILabel = {
        let lable = UILabel()
        lable.textColor = .black
        lable.font = .systemFont(ofSize: 12)
        lable.textAlignment = .center
        lable.isHidden = true
        return lable
    }()
    
    private lazy var sliderCircle: UIView = {
        let view = UIView()
        view.backgroundColor = .cyan
        view.layer.cornerRadius = sliderCircleSize / 2
        view.layer.masksToBounds = true
        view.layer.borderColor = UIColor.black.cgColor
        view.layer.borderWidth = 2
        return view
    }()
    
    private lazy var topSlider: UIView = {
        let view = UIView()
        view.backgroundColor = .cyan
        view.layer.cornerRadius = topSliderHeight / 2
        view.layer.masksToBounds = true
        view.layer.borderColor = UIColor.black.cgColor
        view.layer.borderWidth = 2
        return view
    }()
    
    private lazy var bottomSlider: UIView = {
        let view = UIView()
        view.backgroundColor = .lightGray
        view.layer.cornerRadius = bottomSliderHeight / 2
        view.layer.masksToBounds = true
        return view
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        addControls()
        
        let pan = UIPanGestureRecognizer(target: self, action: #selector(panGestureAction(_:)))
        addGestureRecognizer(pan)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension SliderView {
    
    @objc func panGestureAction(_ pan: UIPanGestureRecognizer) {
        
        let translation = pan.translation(in: self)
        var width = (bounds.size.width - sliderCircleSize / 2) * progress + translation.x
        
        if pan.state == .changed {
            if width > bounds.size.width - sliderCircleSize {
                width = bounds.size.width - sliderCircleSize
            }
            if width < 0 {
                width = 0
            }
            topSlider.snp.updateConstraints { (make) in
                make.width.equalTo(width)
            }
            
            sliderValue.isHidden = false
        }
        
        if pan.state == .ended {
            sliderValue.isHidden = true
            progress = topSlider.frame.size.width / (bounds.size.width - sliderCircleSize / 2)
        }
        
        let value: CGFloat = width / (bounds.size.width - sliderCircleSize)
        sliderValue.text = String(format: "%0.0f", value * 100)
        if let block = touchesMovedHandler {
            block(value, .changed)
        }
    }
    
    func addControls() {
        
        addSubview(bottomSlider)
        bottomSlider.snp.makeConstraints { (make) in
            make.left.equalTo(sliderCircleSize / 2)
            make.right.equalTo(-(sliderCircleSize / 2))
            make.height.equalTo(bottomSliderHeight)
            make.centerY.equalToSuperview()
        }
        
        addSubview(topSlider)
        topSlider.snp.makeConstraints { (make) in
            make.left.centerY.equalTo(bottomSlider)
            make.height.equalTo(topSliderHeight)
            make.width.equalTo(0)
        }
        
        addSubview(sliderCircle)
        sliderCircle.snp.makeConstraints { (make) in
            make.width.height.equalTo(sliderCircleSize)
            make.centerY.equalToSuperview()
            make.centerX.equalTo(topSlider.snp.right)
        }
        
        addSubview(sliderValue)
        sliderValue.snp.makeConstraints { (make) in
            make.centerX.equalTo(sliderCircle)
            make.width.height.equalTo(sliderValueSize)
            make.bottom.equalTo(sliderCircle.snp.top)
        }
    }
    override func draw(_ rect: CGRect) {
        topSlider.snp.updateConstraints { (make) in
            make.width.equalTo(progress * (bounds.size.width - sliderCircleSize / 2))
        }
    }
}
image.png
import UIKit

class ProgressView: UIView {
    
    private let borderWidth: CGFloat = 2
    private var progressView = UIView()
    
    var progress: CGFloat = 0 {
        willSet {
            if newValue > 0 && newValue < 1 {
                let maxWidth = self.bounds.size.width - borderWidth * 2 * 2
                let heigth = self.bounds.size.height - borderWidth * 2 * 2
                progressView.frame = CGRect(x: borderWidth * 2, y: borderWidth * 2, width: maxWidth * newValue, height: heigth)
            }
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        layer.cornerRadius = bounds.size.height * 0.5
        layer.masksToBounds = true
        layer.borderColor = UIColor.white.cgColor
        layer.borderWidth = borderWidth
        backgroundColor = .lightGray
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func draw(_ rect: CGRect) {
        
        progressView.backgroundColor = .white
        progressView.layer.cornerRadius = (bounds.size.height - borderWidth * 2 * 2) * 0.5
        progressView.layer.masksToBounds = true
        addSubview(progressView)
    }
}
image.png
上一篇下一篇

猜你喜欢

热点阅读