首页 > 解决方案 > UISlider 子类不会超出 0 - 1 范围

问题描述

我将子类化UISlider并覆盖maximumValue为 5,minimumValue为 0,isContinuousfalse,并且都跟踪色调颜色。我需要覆盖什么来解决这个问题,例如draw?我尝试将滑块直接设置为大于 1 的值,但仍然没有超过它。任何帮助将不胜感激。

没有例外,调试它显示发送到的值setValue正在相应地改变,我看到的唯一问题是滑块没有在视觉上更新。

class Slider: UISlider {
    private var viewData: ViewData

    // MARK: - Initialization
    init(viewData: ViewData) {
        self.viewData = viewData
        super.init(frame: .zero)
        render(for: viewData)
        translatesAutoresizingMaskIntoConstraints = false
    }

    override public init(frame: CGRect) {
        self.viewData = ViewData(orientation: .vertical, type: .discrete)
        super.init(frame: frame)
        translatesAutoresizingMaskIntoConstraints = false
    }

    required public init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func render(for viewData: ViewData) {
        self.addTarget(self, action: #selector(sliderValueDidChange), for: .valueChanged)
    }

    @objc private func sliderValueDidChange(_ sender: UISlider) {
        self.setValue(sender.value, animated: true)
        Haptic.triggerImpact(.light)
    }

    // MARK: - Overrides
    override var maximumValue: Float {
        get {
            switch viewData.type {
            case .continuous: return 100
            case .discrete: return 5
            }
        }
        set { maximumValue = newValue }
    }

    override var minimumValue: Float {
        get { return 0 }
        set { minimumValue = newValue }
    }

    override var isContinuous: Bool {
        get {
            switch viewData.type {
            case .continuous: return true
            case .discrete: return false
            }
        }
        set { isContinuous = newValue }
    }

    override var minimumTrackTintColor: UIColor? {
        get { return .white }
        set { minimumTrackTintColor = newValue }
    }

    override var maximumTrackTintColor: UIColor? {
        get { return .gray }
        set { minimumTrackTintColor = newValue }
    }

    override open func trackRect(forBounds bounds: CGRect) -> CGRect {
        var newBounds = super.trackRect(forBounds: bounds)
        newBounds.size = CGSize(width: 222, height: 10)
        return newBounds
    }

    override open func thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect {
        var newThumb = super.thumbRect(forBounds: bounds, trackRect: rect, value: value)
        newThumb.size = CGSize(width: 30, height: 30)
        return newThumb
    }

    override open func setValue(_ value: Float, animated: Bool) {
        guard viewData.type == .discrete else {
            super.setValue(value, animated: animated)
            return
        }
        let roundedValue = Int(value)
        super.setValue(Float(roundedValue), animated: animated)
        setNeedsDisplay()
        Haptic.triggerImpact(.light)
    }

标签: iosswift

解决方案


您所有被覆盖的属性都会导致set块中的无限递归。

不要仅仅为了设置特定值而覆盖它们,而是更新您的render方法以设置所需的初始值。

private func render(for viewData: ViewData) {
    self.addTarget(self, action: #selector(sliderValueDidChange), for: .valueChanged)

    minimumValue = 0
    switch viewData.type {
    case .continuous: maximumValue = 100
    case .discrete: maximumValue = 5
    }

    isContinuous = viewData.type == .continuous
    minimumTrackTintColor = .white
    maximumTrackTintColor = .gray
}

除了这个更新,删除那些被覆盖的属性,滑块就可以正常工作了。


推荐阅读