UISlider 在 Anmation 运行时获取值

UISlider get Value while Anmation runs

我使用此功能为 UISlider 设置动画:

func animateSlider(){
    slider.value = Float(min)
    UIView.animate(withDuration: 2.0, animations: {
        self.slider.setValue(Float(self.max), animated:true)
    })

当我点击屏幕时,我想获取当前值,但它只有 returns 最大值。我能做些什么来解决这个问题?

我不认为滑块的值 属性 可以使用 UIView.animate() 进行动画处理。但是,如果您阅读 UISlider 上的文档,您会发现函数

func setValue(Float, animated: Bool)

使用它来将滑块移动到新位置。

不过,如果您想在较长的时间段(如 2 秒)内设置动画变化,您可能需要设置一个重复计时器或 CADisplayLink 计时器,每次触发时都会以较小的增量更改滑块值.

至于你的说法 "When I tap the screen I want to get the current value but it only returns the maximum" 这就是 Cocoa 动画的工作方式。您不能询问 in-flight 动画并获得一个值,该值是您在那一刻正在设置动画的 属性 的值。 (不过,如果您使用重复计时器为滑块设置动画,您 可以 这样做。)

当您安排动画时,Core Animation 会立即设置 model 层的属性,并创建一个您可以检查的 presentation 层。此表示层是您在屏幕上实际看到的内容,可有效查询其属性,例如其 frameboundsposition

您要求立即在动画块中设置模型层的值,而您想要的是通过表示层显示的内容。

当有in-progress动画时,您可以在UISlider上使用此扩展从标签中获取当前显示的呈现值:

extension UISlider {
    var currentPresentationValue: Float {
        guard let presentation = layer.presentation(),
            let thumbSublayer = presentation.sublayers?.max(by: {
                [=10=].frame.height < .frame.height
            })
            else { return self.value }

        let bounds = self.bounds
        let trackRect = self.trackRect(forBounds: bounds)
        let minRect = self.thumbRect(forBounds: bounds, trackRect: trackRect, value: 0)
        let maxRect = self.thumbRect(forBounds: bounds, trackRect: trackRect, value: 1)
        let value = (thumbSublayer.frame.minX - minRect.minX) / (maxRect.minX - minRect.minX)
        return Float(value)
    }
}

及其用法:

func animateSlider() {
    slider.value = 0
    DispatchQueue.main.async {
        UIView.animate(withDuration: 2, delay: 0, options: .curveLinear, animations: {
            self.slider.setValue(1, animated: true)
        }, completion: nil)
    }

    // quarter done:
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
        print(self.slider.currentPresentationValue)
        // prints 0.272757, expected 0.25 with some tolerance
    }

    // half done:
    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
        print(self.slider.currentPresentationValue)
        // prints 0.547876, expected 0.5 with some tolerance
    }

    // three quarters done:
    DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
        print(self.slider.currentPresentationValue)
        // prints 0.769981, expected 0.75 with some tolerance
    }
}