iOS - UISlider在第一次触摸时跳转

时间:2014-04-05 19:27:29

标签: ios uislider

我在使用Xcode 5.1开发的iOS应用程序中添加了UISlider,我无法摆脱以下令人讨厌的行为。当我第一次触摸拇指时,它会跳跃少量。

这是一个详细说明行为的快速示例。

  

当滑块拇指最初位于中心的左侧(例如,处于最小值)时,它会向右跳跃。如果我在iOS模拟器中运行应用程序,拇指会在第一次触摸时跳转而不会拖动任何内容。拇指总是跳向赛道的中心。它不跳的唯一时间是它在轨道的精确中心。即使滑块未连接任何内容,也会出现此行为。

有什么方法可以禁用它吗?

2 个答案:

答案 0 :(得分:4)

今天刚遇到这个问题。出于某种原因,您必须设置自定义拇指图像,并且它可以正常工作。

[self.yourSlider setThumbImage:[UIImage imageNamed:@"customThumb"] forState:UIControlStateNormal];

答案 1 :(得分:0)

同时在2019年和iOS 12中存在该错误

一个老问题,仍然是相关问题。因此,尽管可接受的答案正常工作,但它存在一个小而重要的问题-拇指触摸区域越来越小,而在大多数情况下可触摸区域的增加会导致新的跳跃(已尝试覆盖thumbRect(forBounds和beginTracking方法

让我们修复它!

因此解决方案不是那么复杂,但是有点不方便(需要一些图像资源),比重新实现自己的Slider还要容易

此类的目的是消除UIKit错误,即 在点击过程中跳拇指。 主要技巧是将原始拇指替换为某些图像 其他代码是extendinig攻丝区域,它是: 1)设置具有一些侧面alpha偏移的图像,即带有较大矩形的圆圈

setThumbImage(thumb,for:.normal)

2)较大的图像表示较大的拇指,并且结果跟踪最小值和最大值    在图像的Alpha区域下可见。因此,下一步是设置最小和最大轨道    分别在左右两侧跟踪的图像,

setMinimumTrackImage(anImage,for:.normal)    setMaximumTrackImage(maxSliderImage,for:.normal)

,但是图像还具有一些“隐藏”轨道所需的Alpha区域    拇指的侧面(在完全可见的地方带有最小值/最大值)。

4)当我们的拇指和轨迹较大时,视觉上减小了(分别对应于滑块边界宽度)    需要通过覆盖trackRect(forBounds方法来增加轨道的可见部分。    由于最小/最大图像的一部分是透明的,所以我们不会超出滑块边界轨道 5)作为目标之一是增加拇指的触摸区域,需要覆盖    point(inside point :, with event :)方法在侧面创建可触摸区域

PS:请不要忘记在xcassets中设置最小和最大滑块轨道属性:     1)切片水平和左/右插图     2)拉伸技术

change slicing attributes

class Slider: UISlider {
    /// The value is distance between an image edge and thumb,
    /// Assume that's an image scheme: [...o...] so 3 dots here is imageSideOffset, where 'o' is a thumb
    /// as we want to hide that zone
    private let imageSideOffset: CGFloat = 30

    override func awakeFromNib() {
        super.awakeFromNib()

        if let thumb = UIImage(named: "slider_thumb"),
            let minSliderImage = UIImage(named: "min_slider_track"),
            let maxSliderImage = UIImage(named: "max_slider_track") {
            setThumbImage(thumb, for: .normal)
            setMinimumTrackImage(minSliderImage, for: .normal)
            setMaximumTrackImage(maxSliderImage, for: .normal)
            clipsToBounds = true
        } else {
            assertionFailure("failed to load slider's images")
        }
    }

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        return bounds.insetBy(dx: -imageSideOffset, dy: 0).contains(point)
    }

    override func trackRect(forBounds bounds: CGRect) -> CGRect {
        let superRect = super.trackRect(forBounds: bounds)
        guard let _ = self.thumbImage(for: .normal) else {
            return superRect
        }
        return superRect.insetBy(dx: -imageSideOffset, dy: 0)
    }
}