Ios UISlider设置拇指清晰背景
如何在Ios UISlider设置拇指清晰背景,ios,objective-c,uikit,uislider,Ios,Objective C,Uikit,Uislider,如何在UISlider上设置清晰的拇指背景,使轨迹在拇指后面不可见 这就是我目前所拥有的 但是,我希望它看起来像在iOS摄像头应用程序中一样 您必须添加拇指图像,该图像只有圆形边框,而且是透明的,据我所知,这是唯一可能的选项让我们从实际操作开始,以表明这应该实现OP的目标: 简短的版本是,我使用背景的UIImage,并对其应用以下扩展以添加边框 extension UIImage { func addRoundBorder(width: CGFloat,
UISlider
上设置清晰的拇指背景,使轨迹在拇指后面不可见
这就是我目前所拥有的
但是,我希望它看起来像在iOS摄像头应用程序中一样
您必须添加拇指图像,该图像只有圆形边框,而且是透明的,据我所知,这是唯一可能的选项让我们从实际操作开始,以表明这应该实现OP的目标: 简短的版本是,我使用背景的UIImage,并对其应用以下扩展以添加边框
extension UIImage {
func addRoundBorder(width: CGFloat,
color: UIColor) -> UIImage {
let square = CGSize(width: min(size.width, size.height) + width * 2,
height: min(size.width, size.height) + width * 2)
let imageView = UIImageView(frame: CGRect(origin: .zero, size: square))
imageView.contentMode = .center
imageView.image = self
imageView.layer.cornerRadius = square.width / 2
imageView.layer.masksToBounds = true
imageView.layer.borderWidth = width
imageView.layer.borderColor = color.cgColor
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, false, scale)
guard let context = UIGraphicsGetCurrentContext() else { return self }
imageView.layer.render(in: context)
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result ?? self
}
}
然后,我引入一个我背景的UIImage
,并调用扩展名,使用结果作为我的新缩略图
let image = UIImage(named: "circle")!.addRoundBorder(width: 3.0, color: .yellow)
slider.setThumbImage(image, for: .normal)
虽然这只是为了演示,但我建议使用#imageLiteral
来避免强制转换
下面的屏幕截图将OP通过iOS摄像头应用程序提供的示例图像与我实现的图像进行比较,如下所示。由于每一个的大小,苹果一号的质量允许在比较中有更好的细节
关于@Alladinian的评论,我看到的问题是背景有一个浅色纹理,而使用边框提供了一种视觉方式,可以在按钮与背景融合的地方分解。通过使用OP的背景,它似乎提供了类似的视觉效果。然而,更具挑战性的背景,如图像,肯定会暴露我的设计,并产生不良的结果 TL;博士
简而言之,UISlider
没有简单的API可以重新创建这种行为
前提条件:根据问题,我只是演示如何使拇指透明,而不是显示轨迹。我没有试图完全重新创建相机的滑块
理想溶液
理想的解决方案是创建最小和最大轨迹图像,利用这些图像来避免填充轨迹的一部分。我说这是理想的,因为它直截了当且性能相对较好。不幸的是,UISlider
做了两件事,阻止我们使用这种方法
clipstobunds
设置为true的视图中。将调整最大轨迹的超级视图的大小并剪辑最大轨迹,以确保它在拇指的前端永远不可见
在整个层次结构上禁用clipstobunds
,可以让我们在视图调试器中看到这一点UIImageView
的大小已调整,但当调用UISlider
上的setMinimumTrackImage
时,实际上会创建一个不同的可调整大小的图像。这一点花了一些时间才弄清楚,但可以通过检查内存地址来演示
class TransparentThumbSlider: UISlider {
let thumbWidth: CGFloat = 40
override init(frame: CGRect) {
super.init(frame: frame)
configure()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
func configure() {
setThumbImage(TransparentThumbSlider.thumbImage(diameter: thumbWidth, color: .blue), for: .normal)
addTarget(self, action: #selector(updateTrackImages), for: .valueChanged)
updateTrackImages()
}
static func thumbImage(diameter: CGFloat, color: UIColor) -> UIImage {
let strokeWidth: CGFloat = 4
let halfStrokeWidth = strokeWidth / 2
let totalRect = CGRect(x: 0, y: 0, width: diameter, height: diameter)
let strokeRect = CGRect(x: halfStrokeWidth,
y: halfStrokeWidth,
width: diameter - strokeWidth,
height: diameter - strokeWidth)
let renderer = UIGraphicsImageRenderer(size: totalRect.size)
let image = renderer.image { context in
context.cgContext.setStrokeColor(color.cgColor)
context.cgContext.setLineWidth(strokeWidth)
context.cgContext.strokeEllipse(in: strokeRect)
}
return image
}
static func trackImage(colored color: UIColor,
thumbWidth: CGFloat,
trackWidth: CGFloat,
value: CGFloat,
flipped: Bool) -> UIImage {
let fraction = flipped ? 1 - value : value
let adjustableWidth = (trackWidth - thumbWidth)
let halfThumbWidth = thumbWidth / 2
let fudgeFactor: CGFloat = 2
var totalRect: CGRect
var coloredRect: CGRect
if flipped {
totalRect = CGRect(x: 0, y: 0, width: trackWidth, height: 2)
coloredRect = CGRect(
x: adjustableWidth * value + thumbWidth - fudgeFactor,
y: 0,
width: adjustableWidth * fraction + (halfThumbWidth - fudgeFactor),
height: 2)
} else {
totalRect = CGRect(x: 0, y: 0, width: adjustableWidth * fraction + halfThumbWidth, height: 2)
coloredRect = CGRect(x: 0, y: 0, width: adjustableWidth * fraction, height: 2)
}
let renderer = UIGraphicsImageRenderer(size: totalRect.size)
let image = renderer.image { context in
context.cgContext.setFillColor(color.cgColor)
context.fill(coloredRect)
}
return image
}
@objc func updateTrackImages() {
let trackWidth = trackRect(forBounds: bounds).width
let minimumImage = TransparentThumbSlider.trackImage(
colored: .green,
thumbWidth: thumbWidth,
trackWidth: trackWidth,
value: CGFloat(value),
flipped: false)
setMinimumTrackImage(minimumImage, for: .normal)
let maximumImage = TransparentThumbSlider.trackImage(
colored: .yellow,
thumbWidth: thumbWidth,
trackWidth: trackWidth,
value: CGFloat(value),
flipped: true)
setMaximumTrackImage(maximumImage, for: .normal)
}
var previousBounds: CGRect = .zero
override func layoutSubviews() {
super.layoutSubviews()
// Prevent layout loop
if previousBounds != bounds {
previousBounds = bounds
updateTrackImages()
}
}
}
@LuizfernandoSalvatera问题是什么?@matt its使缩略图(圆形图像)后面的视图在缩略图移动时透明,就像本机相机一样app@LuizFernandoSalvaterra我从来没有注意到。我的猜测是拇指只是一个透明的图像,就像最初的问题(第一个屏幕截图)一样。然后,技巧在于对可调整大小的
minimumTrackImage
和maximumTrackImage
进行切片。前者的右端和后者的左端是透明的,大小固定——正好是拇指圆直径的一半。@matt切片不起作用,因为最大轨迹图像会延长轨迹的长度。@AllenHumphreys是的,我发现了。只是要注意一下(一开始我也被这个问题弄糊涂了)OP想要一个穿过轨迹的透明拇指(想象一个视频在背景中全屏播放-就像照相机应用程序中的缩放滑块一样-你应该能够看到拇指内的动态内容)而且不仅仅是一个静态图像,通过与背景匹配产生透明的错觉…@Alladinian,我明白了。我想这取决于滑块后面的最终背景。假设发布的示例是灰色纹理背景,那么问题就不那么严重了。然而,如果有照片/视频等,那么我的回答也会失败。在这种情况下,他们似乎需要一个定制的滑块。我想说的是,(a)你在这一个上多走了一英里,(b)你应该得到赏金。