swift 自定义滑动进度条UISlider

2023-07-31  本文已影响0人  UILable攻城狮

效果图

IMG_0618.jpg
@objc protocol CABatterySliderViewDelegate: NSObjectProtocol {
    
    /// 滑条拖动回调
    /// - Parameters:
    ///   - sliderView: 滑条
    ///   - value: 位置数值
    @objc optional func sliderView(_ sliderView: CABatterySliderView, valueChanged value: Int)
}

class CABatterySliderView: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupSubviews()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    public var value: Float? {
        didSet {
            guard let value = value else { return }
            let sliderValue = value / maxValue.float
            sliderView.setValue(sliderValue, animated: true)
            DispatchQueue.main.asyncAfter(delay: 0.3) { [weak self] in
                self?.updateValue(sliderValue)
            }
        }
    }
    
    weak var delegate: CABatterySliderViewDelegate?

    private func setupSubviews() {

        addSubviews([wrapperView, minLabel, sliderView, maxLabel])
        wrapperView.addSubviews([wrapperImage, valueLabel])
        wrapperView.snp.makeConstraints { make in
            make.top.equalToSuperview()
            make.width.equalTo(48)
            make.height.equalTo(32)
            make.left.equalTo(minLabel.snp.right).offset(magrin)
        }
        minLabel.snp.makeConstraints { make in
            make.leading.equalTo(16)
            make.top.equalTo(wrapperView.snp.bottom).offset(-10)
            make.width.equalTo(10)
            make.height.equalTo(30)
        }
        maxLabel.snp.makeConstraints { make in
            make.trailing.equalTo(-16)
            make.top.equalTo(wrapperView.snp.bottom).offset(-10)
            make.width.equalTo(40)
            make.height.equalTo(30)
        }
        sliderView.snp.makeConstraints { make in
            make.left.equalTo(minLabel.snp.right).offset(16)
            make.right.equalTo(maxLabel.snp.left).offset(-16)
            make.top.equalTo(wrapperView.snp.bottom).offset(-10)
            make.height.equalTo(30)
        }
        wrapperImage.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        valueLabel.snp.makeConstraints { make in
            make.leading.trailing.equalToSuperview()
            make.top.equalTo(0)
            make.height.equalTo(22)
        }
    }
    
    @objc
    private func sliderValueChange(_ slider: UISlider) {

        let value = Int(round(slider.value * maxValue.float))
        delegate?.sliderView?(self, valueChanged: value)
        
        updateValue(slider.value)
    }
    
    private func updateValue(_ sliderValue: Float) {
        let value = Int(round(sliderValue * maxValue.float))
        let orginX = sliderView.width * CGFloat(sliderValue) + 16 - 24
        wrapperView.snp.updateConstraints { make in
            make.left.equalTo(minLabel.snp.right).offset(orginX)
        }
        valueLabel.text = "\(value)%"
    }
    
    private let magrin = 0
    
    private lazy var minLabel: UILabel = {
        let label = UILabel()
        label.theme_font = Themes.Global.regularFont(size: 14)
        label.theme_textColor = Themes.Text.thirdColor
        label.text = minValue.string
        return label
    }()
    
    private lazy var maxLabel: UILabel = {
        let label = UILabel()
        label.theme_font = Themes.Global.regularFont(size: 14)
        label.theme_textColor = Themes.Text.thirdColor
        label.text = "\(maxValue)%"
        return label
    }()
    private lazy var valueLabel: UILabel = {
        let label = UILabel()
        label.theme_font = Themes.Global.regularFont(size: 14)
        label.textColor = UIColor.colorWithHexString("#252626", 1)
        label.textAlignment = .center
        label.text = "\(minValue)km"
        return label
    }()
    
    private lazy var wrapperView: UIView = {
        let view = UIView()
        return view
    }()
    
    private lazy var wrapperImage: UIImageView = {
        let image = UIImage(named: "battery_icon_label", in: CAHelper.resourceBundle, compatibleWith: nil) ?? UIImage()
        let view = UIImageView()
        view.theme_image = ThemeImagePicker(images: image, image)
        return view
    }()
    
    private lazy var sliderView: CABatterySlider = {
        let image = UIImage(named: "battery_icon_slider", in: CAHelper.resourceBundle, compatibleWith: nil) ?? UIImage()
        let view = CABatterySlider()
        view.minimumValue = 0.0
        view.maximumValue = 1.0
        view.theme_minimumTrackTintColor = Themes.Background.mainColor
        view.theme_maximumTrackTintColor = Themes.Background.subColor
        view.setThumbImage(image, for: .normal)
        view.addTarget(self, action:#selector(sliderValueChange(_:)), for: .valueChanged)
        return view
    }()
    
    private let minValue = 0

    private let maxValue = 100
}

class CABatterySlider: UISlider {
    
    override func trackRect(forBounds bounds: CGRect) -> CGRect {
        let orginY = (bounds.size.height - 6) / 2
        return CGRect(x: bounds.origin.x, y: orginY, width: bounds.size.width, height: 6)
    }
    
    override func thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect {
        var tempRect = rect
        tempRect.origin.x = rect.origin.x - 10
        tempRect.size.width = rect.size.width + 20
        return CGRectInset(super.thumbRect(forBounds: bounds, trackRect: tempRect, value: value), 10, 10)
    }
}

上一篇下一篇

猜你喜欢

热点阅读