如何在Swift中创建连接的滑块?
您可以创建UIBezierPath
,在CAShapeLayer
中使用该路径,并将该图层作为子图层添加到您的视图的layer
。
唯一的问题是确定您的线条的开始点和结束点,可以通过查看滑块的thumbRectForBounds
来完成。假设你使用的标准UISliderView
并简单地旋转它,你应该确保给点转换到父的坐标系:
class ViewController: UIViewController {
@IBOutlet weak var slider1: UISlider!
@IBOutlet weak var slider2: UISlider!
@IBOutlet weak var slider3: UISlider!
lazy var lineLayer: CAShapeLayer = {
let layer = CAShapeLayer()
layer.lineWidth = 3
layer.fillColor = UIColor.clearColor().CGColor
layer.strokeColor = UIColor.redColor().CGColor
return layer
}()
override func viewDidLoad() {
super.viewDidLoad()
[slider1, slider2, slider3].forEach { slider in
slider.transform = CGAffineTransformMakeRotation(CGFloat(-M_PI_2))
}
view.layer.insertSublayer(lineLayer, atIndex: 0)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
lineLayer.frame = view.bounds
updatePathBetweenSliders()
}
@IBAction func didChangeValue(sender: UISlider) {
updatePathBetweenSliders()
}
private func updatePathBetweenSliders() {
let path = UIBezierPath()
path.moveToPoint(slider1.thumbCenter())
path.addLineToPoint(slider2.thumbCenter())
path.addLineToPoint(slider3.thumbCenter())
lineLayer.path = path.CGPath
}
}
其中:
extension UISlider {
func thumbCenter() -> CGPoint {
let thumbRect = thumbRectForBounds(bounds, trackRect: trackRectForBounds(bounds), value: value)
let thumbCenter = CGPoint(x: thumbRect.midX, y: thumbRect.midY)
return convertPoint(thumbCenter, toView: superview)
}
}
国债收益率:
如果你想在任何时候对滑块进行动画处理(就像我在动画GIF结束时那样),你可能不得不重新排序到CADisplayLink
更新值:
let animationDuration = 0.5
var originalValues: [Float]!
var targetValues: [Float]!
var startTime: CFAbsoluteTime!
@IBAction func didTapResetButton(sender: UIButton) {
let sliders = [slider1, slider2, slider3]
originalValues = sliders.map { $0.value }
targetValues = sliders.map { _ in Float(0.5) }
startTime = CFAbsoluteTimeGetCurrent()
let displayLink = CADisplayLink(target: self, selector: #selector(handleDisplayLink(_:)))
displayLink.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
}
func handleDisplayLink(displayLink: CADisplayLink) {
let percent = Float((CFAbsoluteTimeGetCurrent() - startTime)/animationDuration)
let sliders = [slider1, slider2, slider3]
if percent < 1 {
for (index, slider) in sliders.enumerate() {
slider.value = (targetValues[index] - originalValues[index]) * percent + originalValues[index]
}
} else {
for (index, slider) in sliders.enumerate() {
slider.value = targetValues[index]
}
displayLink.invalidate()
}
updatePathBetweenSliders()
}
谢谢。这非常有用。我很好奇 - 有没有办法做到这一点,而不使用transform属性?转换不遵守autol ayout,因此难以清洁地定位这些垂直滑块。我试图把它们放在堆栈视图中,但我试图获得我想要的大小时遇到了各种问题。 – kubernetes
我试图把它们放在堆栈视图中,发现在涉及到转换时会变得更加复杂。我使用带有自动布局的转换滑块呈现了上述内容,并且它的工作令人惊讶(尽管故事板看起来很奇怪)。不过,你确定也可以制作自己的垂直滑块控件,因为它并不复杂。我确信有第三方的垂直滑块控件,虽然我没有真正看过,当然也不能担保。 – Rob
任何截图或代码,你试图做到这一点? –