iOS:新しいautolayout制約(高さ)をアニメーション化する方法


123

これまでにautolayout制約を扱ったことはありません。私が作業している小さな新しいアプリがあり、NIBのビューがデフォルトで自動レイアウトになっていることに気付きました。それで、私それを使って作業する機会を得て、Appleがこれでどこに向かっているのかを理解しようとするだろうと考えました。

最初の課題:

MKMapViewのサイズを変更する必要があり、それを新しい位置にアニメーション化したいと思います。私が慣れている方法でこれを行うと:

[UIView animateWithDuration:1.2f
     animations:^{
         CGRect theFrame = worldView.frame;
         CGRect newFrame = CGRectMake(theFrame.origin.x, theFrame.origin.y, theFrame.size.width, theFrame.size.height - 170);
         worldView.frame = newFrame;
}];

...その後、兄弟ビューが更新されるたびにMKMapViewが元の高さに「スナップ」します(私の場合、UISegmentedControlのタイトルが更新されています[myUISegmentedControl setTitle:newTitle forSegmentAtIndex:0])。

だから、私は考えて私がやりたいことは、それがあることUISegmentedControlの先頭に相対的であることに、親ビューの絶頂に等しいからMKMapViewの制約を変更されカバーします:V:[MKMapView]-(16)-[UISegmentedControl]

MKMapViewの高さを短くして、マップビューの下の一部のコントロールが表示されるようにしたいのですが。これを行うには、固定フルサイズビューから、UISegmentedControlの上部が下部に制限されているビューに制限を変更する必要があると思います。ビューが新しいサイズに縮小するときにアニメーションを表示したいと思います。

これをどうやってやるの?

編集- このアニメーションはされていないアニメーションビューの下部には、170を瞬時に動かすんが。

    [UIView animateWithDuration:1.2f
         animations:^{
             self.nibMapViewConstraint.constant = -170;

    }];

そしてnibMapViewConstraint下の垂直方向のスペースの制約にIBにまで配線されています。


1
[UIView animateWithDuration ..]ブロックで制約の定数値を簡単に変更して、高さの変化をアニメーション化できることを知っています。その制約のIBOutletを作成してxibに接続するか、コードで作成した場合はそれへの参照を保持する必要があります(またはすべての制約をループして探します)。relatedByの変更をアニメーション化する方法はわかりませんが、定数の他の値ではなく定数のみを変更する必要があることを読みました(他の値の場合は、新しい制約を作成します)。
yuf

うーん。できると思ったのですが、アニメーションではありません。正常に変更され、アニメーションブロックにありますがアニメーション化されていません!?!
Meltemi

ここで私の答えを見つけました:< stackoverflow.com/questions/12926566/… >
Meltemi

1
[view layoutIfNeeded]を忘れないでください。それは私の問題でもありました。それは私の問題を解決した同じ質問です。
yuf、2012年

回答:


179

制約を更新した後:

[UIView animateWithDuration:0.5 animations:^{[self.view layoutIfNeeded];}];

self.view含まれているビューへの参照に置き換えます。


4
これはビュー自体に有効ですが、そのビューに制約があるビューは即座に移動します。私は何をしますか?ty
dietbacon 2013

7
これらのビューでも必要な場合は、レイアウトを呼び出す必要があります。ただし、これによってビューの更新がアニメーション化されるため、実際には正しく機能しません。他のビューでのみ制約調整をアニメーション化するにはどうすればよいですか?
ngb 2013

3
注意:UIViewAnimationOptionBeginFromCurrentStateレイアウト制約を使用する場合、アニメーションの前にレイアウト制約が設定されます!
Robert

12
layoutIfNeededこれらの各ビューを呼び出す代わりに、単に呼び出す[[self.view superview] layoutIfNeeded];
Flying_Banana

2
@ngbでは、アニメーションブロックの制約定数を変更する必要があります。これにより、アニメーションによってコンストレイントが変化し、を使い続けることができますUIViewAnimationOptionBeginFromCurrentState
Eran Goldin

86

これは私にとっては機能します(iOS7とiOS8 +の両方)。調整する自動レイアウト制約をクリックします(インターフェースビルダーなどで、上部制約)。次に、これをIBOutletにします。

@property (strong, nonatomic) IBOutlet NSLayoutConstraint *topConstraint;

上向きにアニメートします。

    self.topConstraint.constant = -100;    
    [self.viewToAnimate setNeedsUpdateConstraints]; 
    [UIView animateWithDuration:1.5 animations:^{
        [self.viewToAnimate layoutIfNeeded]; 
    }];

元の場所に戻るアニメーション

    self.topConstraint.constant = 0;    
    [self.viewToAnimate setNeedsUpdateConstraints];  
    [UIView animateWithDuration:1.5 animations:^{
        [self.viewToAnimate layoutIfNeeded];
    }];

2
ワオ!!これは実際に機能します!この答えは私にとって目を見張るものでした。どうもありがとうございました!-Erik
Erik van der Neut 2014年

2
@ErikvanderNeut私にとっても役に立ちました。今後は、フレームの位置ではなく、コンストレインをアニメーション化します。
DevC 2014年

追加をお見逃しなく:[containerView layoutIfNeeded]; animateWithDurationブロックの前に、保留中のすべてのレイアウト操作が完了していることを確認します。
ingconti

11

autolayoutでアニメーションを使用する方法を説明するアップル自体からの非常に良いチュートリアルがあります。このリンクをたどって、「Auto layout by example」という名前のビデオを見つけてください。これにより、autolayoutに関する興味深いことがわかります。最後の部分は、アニメーションの使用方法です。



1

ほとんどの人は、自動レイアウトを使用してビューにアイテムをレイアウトし、レイアウト制約を変更してアニメーションを作成します。

多くのコードなしでこれを行う簡単な方法は、ストーリーボードでアニメーション化するUIViewを作成してから、UIViewを終了する非表示のUIViewを作成することです。xcodeのプレビューを使用して、両方のUIViewが希望どおりの場所にあることを確認できます。その後、最後のUIViewを非表示にし、レイアウト制約を入れ替えます。

自分で記述したくない場合は、SBPと呼ばれるレイアウト制約を交換するためのpodfileがあります。

こちらがチュートリアルです。


0

IBOutlet referenceこれの代わりに制約をさらに使用する必要はありません。ライブラリを使用して、任意のビューによって、またはビューから直接accessまたはupdateすでに適用された制約を適用できます。このライブラリは、の動作も管理しています。ProgrammaticallyInterface BuilderKVConstraintExtensionsMasterCumulativeNSLayoutConstraint

containerViewに高さ制約を追加するには

 CGFloat height = 200;
 [self.containerView applyHeightConstrain:height];

containerViewの高さ制約をアニメーションで更新するには

[self.containerView accessAppliedConstraintByAttribute:NSLayoutAttributeHeight completion:^(NSLayoutConstraint *expectedConstraint){
        if (expectedConstraint) {
            expectedConstraint.constant = 100;

            /* for the animation */ 
            [self.containerView  updateModifyConstraintsWithAnimation:NULL];
      }
    }];
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.