UISlider
的默认行为是它的拇指不以轨道的开头/结尾为中心。如下所示:
我想修改它的行为:
拇指的中心位于开始或结束位置。
我试图用空UIView
覆盖开始/结束。效果是看起来几乎没问题,但拇指有阴影,在某些位置显示我的黑客(我可以忍受),但是我的 hacky 视图覆盖了一点拇指并抓住了它触摸事件(即使禁用了用户交互)。
所以我想我需要在拇指和轨道之间打包我的 hacky 视图。可能没有操纵其内部视图。有什么想法吗?
答案 0 :(得分:2)
UISlider类具有方法thumbRect(forBounds:trackRect:value:),您可以重写该方法以控制滑块的拇指图像的绘制矩形。因此,假设此空间为5点(可能会因您使用的拇指图像而异),我们可以执行以下操作:
UISlider
并重写thumbRect(forBounds:trackRect:value:)
以将自己吸引到流程中完整的代码应如下所示:
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)
}
}
答案 1 :(得分:0)
像我这样的懒人的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)
}
}
答案 2 :(得分:0)
当最小值 < 0 时,Mostafa 和 ergunkocak 的解决方案对我来说失败了。这就是我最终使用的:
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
}
}