如何在Swift中创建连接的滑块?

时间:2016-08-04 18:31:55

标签: ios swift xcode swift2

我正在尝试使用3个垂直滑块创建一个控件。我希望滑块上的可拖动点有连接它们的线条。关于如何制作这个的任何建议?

1 个答案:

答案 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)
    }
} 

产量:

lines between sliders

如果您想在任何时候为滑块设置动画(就像我在动画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()
}