我正在尝试使用3个垂直滑块创建一个控件。我希望滑块上的可拖动点有连接它们的线条。关于如何制作这个的任何建议?
答案 0 :(得分:2)
您可以创建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()
}