【问题标题】:UISlider with thumb center over the start and end of trackUISlider 拇指中心位于轨道的起点和终点
【发布时间】:2016-11-09 08:10:22
【问题描述】:

UISlider 的默认行为是它的拇指不在轨道的开始/结束处。如下:

我想修改它的行为以获得:

拇指的中心可以位于开始或结束位置。

我试图用空的UIView 覆盖开始/结束。效果是看起来几乎没问题,但是拇指有阴影,可以在某些位置显示我的 hack(我可以忍受),但是我的 hacky 视图覆盖了一点拇指并捕获了它的触摸事件(甚至当用户交互被禁用时)。

所以我想我需要在拇指和轨道之间打包我的 hacky 视图。可能不会操纵其内部观点。有什么想法吗?

【问题讨论】:

  • 嗨,现在我面临同样的问题,但用户界面不同,没有拇指图像(在 xib 中给拇指颜色以清除)。现在,如果我将滑块值设置为 0,最小值将最小为 4 到 6 个像素,我不能设置零和最大值。如果您找到解决方案,请帮助我。
  • 嗨,如何在滑块的开始和结束处添加垂直线?我尝试添加 minTrackImage/maxTrackImage 但它们的轨道空间很大。可以分享一下解决方法吗?

标签: ios uikit uislider


【解决方案1】:

UISlider 类有一个方法thumbRect(forBounds:trackRect:value:),您可以覆盖该方法来控制滑块缩略图的绘制矩形。因此,假设这个空间是 5 个点(可能会因您使用的拇指图像而异),我们可以执行以下操作:

  1. 子类 UISlider 并覆盖 thumbRect(forBounds:trackRect:value:) 以将我们自己挂钩到进程中
  2. 定义 thumbSpace(我假设它是 5),我们可以从 thumbSpace 计算起始偏移量(滑块前 5 个点)和结束偏移量(滑块后 5 个点)。
  3. 计算与当前值、minValue 和 maxValue 相关的拇指平移(换句话说,根据当前值,我们稍微移动拇指以覆盖我们不想显示的空间)
  4. 将一个移位的矩形(应用 x 平移后)返回给 super 方法以进行常规计算

完整的代码应该如下:

class CustomSlider: UISlider {
    let defaultThumbSpace: Float = 5
    lazy var startingOffset: Float = 0 - defaultThumbSpace
    lazy var endingOffset: Float = 2 * defaultThumbSpace

    override func thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect {
        let xTranslation =  startingOffset + (minimumValue + endingOffset) / maximumValue * value
        return super.thumbRect(forBounds: bounds,
                               trackRect: rect.applying(CGAffineTransform(translationX: CGFloat(xTranslation),
                                                                          y: 0)),
                               value: value)
    }
}

【讨论】:

  • 滑动时效果很好,但是当您再次抓住拇指接近一个极限时,它会很快跳到另一个值,有什么线索可以解决这个问题吗?
【解决方案2】:

Swift 5 版本适合像我这样的懒人 :)

class CustomSlider: UISlider {

    private let trackHeight: CGFloat = 8

    override func trackRect(forBounds bounds: CGRect) -> CGRect {
        let point = CGPoint(x: bounds.minX, y: bounds.midY)
        return CGRect(origin: point, size: CGSize(width: bounds.width, height: trackHeight))
    }

    private let thumbWidth: Float = 52
    lazy var startingOffset: Float = 0 - (thumbWidth / 2)
    lazy var endingOffset: Float = thumbWidth

    override func thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect {
        let xTranslation =  startingOffset + (minimumValue + endingOffset) / maximumValue * value
        return super.thumbRect(forBounds: bounds, trackRect: rect.applying(CGAffineTransform(translationX: CGFloat(xTranslation), y: 0)), value: value)
    }
}

【讨论】:

    【解决方案3】:

    当最小值为

    class CustomSlider: UISlider {
        var customThumbSpacing: CGFloat?
    
        override func thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect {
            if let customThumbSpacing = customThumbSpacing {
                let minOrigin = super.thumbRect(forBounds: bounds, trackRect: rect, value: minimumValue).origin.x
                let maxOrigin = super.thumbRect(forBounds: bounds, trackRect: rect, value: maximumValue).origin.x
                let defaultFrame = super.thumbRect(forBounds: bounds, trackRect: rect, value: value)
                
                let newOrigin = defaultFrame.origin.x.map(
                    from: minOrigin...maxOrigin,
                    to: minOrigin-customThumbSpacing...maxOrigin+customThumbSpacing)
                            
                return CGRect(x: newOrigin,
                              y: defaultFrame.origin.y,
                              width: defaultFrame.width,
                              height: defaultFrame.height)
            } else {
                return super.thumbRect(forBounds: bounds, trackRect: rect, value: value)
            }
        }
    }
    
    extension CGFloat {
        func map(from: ClosedRange<CGFloat>, to: ClosedRange<CGFloat>) -> CGFloat {
            let result = ((self - from.lowerBound) / (from.upperBound - from.lowerBound)) * (to.upperBound - to.lowerBound) + to.lowerBound
            return result
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-20
      • 1970-01-01
      • 1970-01-01
      • 2018-01-04
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      相关资源
      最近更新 更多