2017-06-03 8 views
2

UIViewPropertyAnimatorのオンラインで見つかったすべての例では、ビューが一般的にレイアウトされる方法である自動レイアウトを使用するのではなく、フレームを設定することによってレイアウトされたビューを使用します。自動レイアウトを使用する場合、ビューは私が望む位置にアニメートしますが、その後はモデルの位置に戻す方法がわかりません。自動レイアウトでUIViewPropertyAnimatorを使用するには?

// Move a view that is constrained to the center of its superview 
UIViewPropertyAnimator(duration: 1, curve: .linear) { 
    testView.center = CGPoint(x: 10, y: 10) 
}.startAnimation() 

明らかに何らかの制約が追加されていますか?アニメーションを実行する前後にコンテナビューの制約を記録しました。

CONSTRAINTS BEFORE: 
view: [<NSLayoutConstraint:0x618000094f00 UIView:0x7fd764004050.centerX == UIView:0x7fd75fd00000.centerX (active)>, <NSLayoutConstraint:0x618000092de0 UIView:0x7fd764004050.centerY == UIView:0x7fd75fd00000.centerY (active)>] 

CONSTRAINTS AFTER: 
view: [<NSLayoutConstraint:0x618000094f00 UIView:0x7fd764004050.centerX == UIView:0x7fd75fd00000.centerX (active)>, <NSLayoutConstraint:0x618000092de0 UIView:0x7fd764004050.centerY == UIView:0x7fd75fd00000.centerY (active)>, <NSLayoutConstraint:0x6100000922a0 'UIView-Encapsulated-Layout-Height' UIView:0x7fd75fd00000.height == 667 (active)>, <NSAutoresizingMaskLayoutConstraint:0x610000092570 h=-&- v=-&- 'UIView-Encapsulated-Layout-Left' UIView:0x7fd75fd00000.minX == 0 (active, names: '|':UIWindow:0x7fd75fc07110)>, <NSAutoresizingMaskLayoutConstraint:0x610000092890 h=-&- v=-&- 'UIView-Encapsulated-Layout-Top' UIView:0x7fd75fd00000.minY == 0 (active, names: '|':UIWindow:0x7fd75fc07110)>, <NSLayoutConstraint:0x610000091670 'UIView-Encapsulated-Layout-Width' UIView:0x7fd75fd00000.width == 375 (active)>] 

ここでは何が起こっていますか?自動レイアウトで配置されたビューのアニメーションをどのように処理すればよいですか?アップルはユーザーにフレームベースのレイアウトに戻ることを奨励していますか?

答えて

7

あなたは自動レイアウトUIViewPropertyAnimatorを使用することができますが、あなたの代わりに、ビューのフレームの制約を変更し、クロージャの内部でlayoutIfNeeded()を呼び出す必要があります。

最初の例は:ストーリーボードのビューを作成

制約constantを修正することによりアニメート。ビューのcenterXをスーパービューの先頭に合わせるように制約を作成します。その制約に@IBOutletを作成し、centerXConstraintとします。同様に、ビューのcenterYをスーパービューの先頭と同じ位置に配置するcenterYConstraintを作成します。これらの制約の両方にはconstant = 0が必要です。

制約に@IBOutlet Sを作成します。

@IBOutlet weak var centerXConstraint: NSLayoutConstraint! 
@IBOutlet weak var centerYConstraint: NSLayoutConstraint! 

が新しい位置に制約のconstant値を設定し、UIViewPropertyAnimatorの内側view.layoutIfNeeded()を呼び出す:

// Make sure view has been laid out 
view.layoutIfNeeded() 

// Set new X and Y locations for the view 
centerXConstraint.constant = 50 
centerYConstraint.constant = 80 

UIViewPropertyAnimator(duration: 1, curve: .easeInOut) {    
    self.view.layoutIfNeeded() 
}.startAnimation() 

第二の例新しい制約をアクティブにすることでアニメーション化

(たとえばredViewのために)あなたのストーリーボード内のビューを作成し、あなたのコードでそれに@IBOutletを作成します。

@IBOutlet weak var redView: UIView! 

// Outlets to the constraints set in the Storyboard 
@IBOutlet weak var topConstraint: NSLayoutConstraint! 
@IBOutlet weak var leadingConstraint: NSLayoutConstraint! 
ビューの位置を制御する制約に @IBOutletの作成

次にアニメーション化するとき:

// Make sure view has been laid out 
view.layoutIfNeeded() 

// Deactivate the old constraints 
topConstraint.isActive = false 
leadingConstraint.isActive = false 

// Active new constraints that move view to the bottom right   
redView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true 
redView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true 

// Animate the change   
UIViewPropertyAnimator(duration: 1, curve: .easeInOut) { 
    self.view.layoutIfNeeded() 
}.startAnimation() 

これは、従来のUIViewアニメーションブロックよりもどのように優れていますか?

UIViewPropertyAnimatorは、さまざまな方法でアニメーションを制御するように設定できるオブジェクトです。

  1. が完了したアニメーションの一部を見つけるアニメーション
  2. を一時停止アニメーション
  3. を開始し、アニメーションを通じてスクラブその
  4. にスライド値を設定:ここでは示して完全な例がありますスライダーで

Scrubbing animation demo

class ViewController: UIViewController { 

    @IBOutlet weak var redView: UIView! 
    @IBOutlet weak var centerXConstraint: NSLayoutConstraint! 
    @IBOutlet weak var centerYConstraint: NSLayoutConstraint! 
    @IBOutlet weak var slider: UISlider! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     slider.isHidden = true 
    } 

    var myAnimator: UIViewPropertyAnimator? 

    @IBAction func startAnimation(_ sender: UIButton) { 
     view.layoutIfNeeded() 

     centerXConstraint.isActive = false 
     centerYConstraint.isActive = false 

     redView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true 

     redView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true 

     myAnimator = UIViewPropertyAnimator(duration: 10, curve: .easeInOut) { 

      self.view.layoutIfNeeded() 
     } 

     myAnimator?.startAnimation() 
    } 

    @IBAction func pauseAnimation(_ sender: UIButton) { 
     guard let myAnimator = myAnimator else { return } 

     myAnimator.pauseAnimation() 

     print("The animation is \(String(format: "%.1f", myAnimator.fractionComplete * 100))% complete") 

     slider.value = Float(myAnimator.fractionComplete) 
     slider.isHidden = false 
    } 

    @IBAction func scrub(_ sender: UISlider) { 
     myAnimator?.fractionComplete = CGFloat(sender.value) 
    } 
} 
+0

これは、UIViewアニメーションブロックと同じ古い方法です。改善はありませんか?また、それらの制約はどのように生成されますか? – GoldenJoe

+0

UIViewPropertyAnimatorは、アニメーションを一時停止、反転などできるように設定できるオブジェクトです。速度などを制御する独自のカーブを作成できます。 – vacawama

+0

私はあなたが制約について尋ねていることを理解していません。私は、ビューに新しい制約を適用してアニメートする方法をデモしていました。 – vacawama

関連する問題