2017-02-08 13 views
0

私は、離散ポイントを持つスライダーに作成しようとしているxibを持つUIViewサブクラスを持っています。カスタムスライダーとオートレイアウトの問題

私は「トラック」と「親指」を持っています。トラックに沿って、4つの円が均等に配置されていて、親がドラッグされているときにスナップすることができます。

私が使用しているコードは以下の通りです:

override func awakeFromNib() { 
    // Layout circles 
    for index in stride(from: numberOfCircles, to: 0, by: -1) { 
     let xValue = (((index - 1)/(numberOfCircles - 1))*track.frame.size.width) - circleSize/2 + thumbWidth.constant/2 
     makeCircle(withXValue: xValue) 
    } 
} 

fileprivate func makeCircle(withXValue xValue: CGFloat) { 
    let circle = CAShapeLayer() 
    circle.path = UIBezierPath(ovalIn: CGRect(x: xValue , y: self.frame.height/2 - circleSize/2, width: circleSize, height: circleSize)).cgPath 
    circle.fillColor = UIColor(red: 238/255, green: 79/255, blue: 84/255, alpha: 1).cgColor 
    self.layer.addSublayer(circle) 
} 

私はこれが仕事だと思う、しかし、track.frame.size.widthが正しくありません。これは、このUIViewサブクラスを別のビューに追加し、autolayoutを使用してその幅を設定するためです。 awakeFromNib()に返す幅は、xibの値です。 この問題を解決するためにトラックの実際の幅をどのように得ることができますか?フレームが変更された場合、あなたがそれらにアクセスできるようにプロパティに、あなたのサークルの層を保存

circle.position = CGPoint(x: xValue , y: self.frame.height/2 - circleSize/2) 

+0

'と、それが唯一の二度目' layoutSubviews(呼び出されることを確認してください:オーバーライドメソッドlayoutSublayers(of layer: CALayer)は、新しいフレームの値を使用して位置を設定するにはそれが動作します。しかし、それは少しハッキリのようです。 – Tometoyou

+0

'layoutSubviews()'を試してください。ただし、複数回呼び出される可能性があります。編集:ちょうどあなたのコメントを見た - はい、少し粘り気ですが、最高の方法。 (それがビューコントローラの場合は、より良いオプションがあります。) – dfd

答えて

0

は、代わりにCALayerクラスのこの使用positionプロパティの位置

circle.path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: circleSize, height: circleSize)).cgPath 

上のパスを独立させます。あなたのレイヤーの作成メソッドは、それが作成したレイヤーを返します。makeCircle(withXValue xValue: CGFloat) -> CAShapeLayer。内部に保存してくださいawakeFromNib()circles.append(makeCircle(withXValue: calculateXValueForCircle(atIndex: index))

ビューのフレームが変更されると、layoutSublayersというメソッドが呼び出されます。 `)私はlayoutSubviews`でawakeFromNib() `(`からコードを置く場合)

override func layoutSublayers(of layer: CALayer) { 
     super.layoutSublayers(of: layer) 
     if layer == self.layer { 
      for (index, circle) in circles.enumerated() { 
       let newX = calculatePositionForCircle(atIndex: index) 
       let newY = self.frame.height/2 - circleSize/2 
       circle.position = CGPoint(x: newX, y: newY) 
      } 
     } 
    } 

    // Calculating X position better move in method so you don't dublicate your code 
    fileprivate func calculatePositionForCircle(atIndex index: Int) -> CGFloat { 
     return (((index - 1)/(numberOfCircles - 1))*track.frame.size.width) - circleSize/2 + thumbWidth.constant/2 
    } 
関連する問題