2016-08-04 5 views
0

私は3つの垂直スライダでコントロールを作成しようとしています。私は、スライダのドラッグ可能な点にそれらを結ぶ線を持たせたい。これを作る方法についてのアドバイス?Swiftで接続されたスライダーを作成するには?

+0

これを行うにはどうすればよいですか? –

答えて

1

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() 
} 
+0

ありがとうございます。これは非常に便利でした。私は不思議です - 変換プロパティを使用せずにこれを行う方法はありますか?変形はオートアイトを遵守しないため、これらの垂直スライダをきれいに配置することは困難です。私はスタックビューでそれらを入れてみましたが、私が望むサイズを取得しようとしている間、あらゆる種類の問題に遭遇しました。 – kubernetes

+0

私はそれらをスタックビューに入れようとしましたが、変換があったときにはもっと複雑になることがわかりました。私は自動レイアウトで変形スライダーを使用して上記をレンダリングし、それは驚くほどうまくいった(ストーリーボードは奇妙に見えたが)。しかし、複雑なことではないので、独自の垂直スライダコントロールを作成することもできます。そして、私は本当に見ていないと確かにすべてのために保証することはできませんが、そこにサードパーティ垂直スライダーコントロールがあると確信しています。 – Rob

関連する問題