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

Posted

技术标签:

【中文标题】iOS - UISlider 在第一次触摸时跳跃【英文标题】:iOS - UISlider jumps on first touch 【发布时间】:2014-04-05 19:27:29 【问题描述】:

我已将UISlider 添加到我正在使用 Xcode 5.1 开发的 ios 应用程序中,但我无法摆脱以下烦人的行为。当我第一次触摸拇指时,它会轻微跳跃。

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

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

有什么办法可以禁用它?

【问题讨论】:

@ipinak 很明显。不需要代码。 这纯粹是模拟器现象吗?你有一个方便的设备可以试一试吗?如果它只是一个模拟器的东西,你应该笑着忽略它。鼠标光标不是大胖手指,可能是模拟器在做某种补偿。 不,当我在 iPad 上测试时也会发生这种情况。我刚才提到模拟器是为了强调“跳跃”不是我无意中在 ipad 屏幕上移动手指的结果。 好的,这个是已知的,有解决办法:***.com/questions/20903317/… 太棒了!非常感谢,不知道我是怎么错过其他答案的。 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

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

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

让我们修复它!

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

这个类的目的是消除 UIKit 错误,这是 在敲击时跳跃拇指。 主要的技巧是用一些图像替换原始拇指 其他代码是扩展攻丝区域,即: 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 中设置 min 和 max 滑块轨道属性: 1)切片水平和左/右插图 2) 拉伸技术

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)
    

【讨论】:

以上是关于iOS - UISlider 在第一次触摸时跳跃的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 折叠动画 UISlider

UISlider 释放触摸时过于敏感

触摸结束时如何更改 UISlider Thumb 外观

首次显示时如何使 UISlider 变粗?

iOS - 手势和uislider

在较长的触摸时增加跳跃高度,直到最大高度