如何防止UISlider在捕捉/步进时跳入适当位置

时间:2018-10-24 16:01:22

标签: ios swift scroll uislider

我有一个UISlider,可以捕捉到5个不同的位置。

slider.minimumValue = 1
slider.maximumValue = 5

贴合效果很好,但会突然出现,并且无法顺利贴合到位。有点“跳”到位

我尝试使滚动动画(无效):

@objc func onSliderValChanged(_ sender: UISlider) {
    UIView.animate(withDuration: 0.5) {
        self.slider.value = round(sender.value)
        self.slider.setValue(round(sender.value), animated: true)
    }
}

我还尝试添加panGesture(无效):

panGesture = UIPanGestureRecognizer(target: self, action: #selector(panGestureHandler(_:)))
slider.addGestureRecognizer(panGesture)

@objc func panGestureHandler(_ recognizer: UIPanGestureRecognizer){

    let currentPoint = recognizer.location(in: slider)
    let percentage = currentPoint.x/slider.bounds.size.width

    let delta = Float(percentage) * (slider.maximumValue - slider.minimumValue)
    let value = slider.minimumValue + delta
    slider.setValue(round(value), animated: true)
}

如何使滑块平滑滚动但仍能固定到位?

这是未经上述尝试的原始代码:

let slider: UISlider = {
    let slider = UISlider()
    slider.translatesAutoresizingMaskIntoConstraints = false
    slider.minimumValue = 1
    slider.maximumValue = 5
    slider.value = 3
    slider.isContinuous = true
    slider.addTarget(self, action: #selector(onSliderValChanged(_:)), for: .valueChanged)
    return slider
}()

@objc func onSliderValChanged(_ sender: UISlider) {

    slider.value = round(sender.value)
}

func setAnchors() {
    slider.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 0).isActive = true
    slider.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 10).isActive = true
    slider.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -10).isActive = true
}

1 个答案:

答案 0 :(得分:0)

UISlider使用多个UIImageView子视图进行绘制。当您更改滑块的value时,滑块会自行发送setNeedsLayout,但实际上不会更改其子视图的框架,直到在运行循环的布局阶段收到layoutSubviews为止。

要动画化值的变化,您需要使滑块在动画块内布置其子视图。因此:

@IBAction func sliderValueChanged(_ slider: UISlider) {
    slider.value = round(slider.value)
    UIView.animate(withDuration: 0.2, animations: {
        slider.layoutIfNeeded()
    })
}