202

横向きの巨大なキーボードによってブロックされるように、いくつかのビューをアニメーション化しようとしています。フレームを単純にアニメーション化すればうまく機能しますが、これは非生産的であり、代わりに NSLayoutConstraints を更新する必要があると他の人が示唆しています。ただし、それらはアニメーション化できないようです。彼らを成功に導いた人はいますか?

//heightFromTop is an NSLayoutConstraint referenced from IB
[UIView animateWithDuration:0.25 animations:^{
    self.heightFromTop.constant= 550.f;
}];

その結果、問題の高さまで瞬時にジャンプします。

4

4 に答える 4

489

この正確なパターンに従ってください:

self.heightFromTop.constant = 550.0f;
[myView setNeedsUpdateConstraints];

[UIView animateWithDuration:0.25f animations:^{
   [myView layoutIfNeeded];
}];

どこに追加されmyViewたビューです。self.heightFromTopアニメーション ブロックで行った唯一のことは制約を設定することであり、レイアウトがすぐには発生しないため、ビューが「ジャンプ」しています。あなたのコードでは、 を設定した後の次の実行ループでレイアウトが発生し、heightFromTop.constantその時までに既にアニメーション ブロックの範囲外になっています。

Swift 2 では:

self.heightFromTop.constant = 550
myView.setNeedsUpdateConstraints()

UIView.animateWithDuration(0.25, animations: {
   myView.layoutIfNeeded()
})
于 2012-10-17T03:25:31.227 に答える
14

@Centurion のアプローチを試してみましたが、ストーリーボードから読み込まれた場合、ビューが間違ったフレームにアニメーション化されます。理由はわかりませんが、最初layoutIfNeededをに置き換えると問題は解決します。updateConstraintsIfNeeded誰かが説明を与えることができれば、それは大歓迎です。

[self.view updateConstraintsIfNeeded];
[UIView animateWithDuration:1.0 animations:^{
    self.myConstraint.constant= 100;
    [self.view layoutIfNeeded];
}];
于 2014-01-24T00:59:05.523 に答える
6

私は同様の問題を抱えていましたが、このスレッドはそれを乗り越えるための大きな助けになりました.

erurainon からの回答は私を正しい軌道に乗せましたが、少し異なる回答を提案したいと思います。アニメーション化されたトランジションの代わりにジャンプがまだあったため、erurainon から提案されたコードは機能しませんでした。cnotethegr8 が提供するリンクから、実用的な答えが得られました。

自動レイアウト ガイド https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/AutoLayoutbyExample/AutoLayoutbyExample.html (ページの一番下まで)。

erurainon による回答とのいくつかの違い:

  1. アニメーション メソッドを呼び出す前に (myView の setNeedsUpdateConstraints の代わりに)、コンテナー ビューで layoutIfNeeded を呼び出します。
  2. アニメーション ブロックに新しい制約を設定します。
  3. myView ではなく、アニメーション メソッドのコンテナー ビューで (制約を設定した後)、layoutIfNeeded を呼び出します。

これは、上記のリンクで Apple が提案したパターンに従います。

ボタンをクリックするだけで特定のビューを閉じたり、展開したりして、特定のビューをアニメーション化したいと考えていました。私は自動レイアウトを使用していて、コードに寸法 (私の場合は高さ) をハードコーディングしたくないので、viewDidLayoutSubviews で高さをキャプチャすることにしました。autolayout を使用する場合は、viewWillAppear ではなく、このメソッドを使用する必要があります。viewDidLayoutSubviews は何度も呼び出される可能性があるため、初期化の最初の実行を知らせるために BOOL を使用しました。

// Code snippets

@property (weak, nonatomic) IBOutlet UIView *topView; // Container for minimalView
@property (weak, nonatomic) IBOutlet UIView *minimalView; // View to animate

@property (nonatomic) CGFloat minimalViewFullHeight; // Original height of minimalView

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *minimalViewHeightConstraint;

@property (nonatomic) BOOL executedViewDidLayoutSubviews;


- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];


    // First execution of viewDidLayoutSubviews?
    if(!self.executedViewDidLayoutSubviews){
        self.executedViewDidLayoutSubviews = YES;


        // Record some original dimensions
        self.minimalViewFullHeight = self.minimalView.bounds.size.height;


        // Setup our initial view configuration & let system know that 
        // constraints need to be updated.
        self.minimalViewHeightConstraint.constant = 0.0;
        [self.minimalView setNeedsUpdateConstraints];

        [self.topView layoutIfNeeded];
    }
}

アクション スニペット全体のサイズを変更する

// An action to close our minimal view and show our normal (full) view
- (IBAction)resizeFullAction:(UIButton *)sender {

    [self.topView layoutIfNeeded];

    [UIView transitionWithView:self.minimalView
                  duration:1.0
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                    self.minimalViewHeightConstraint.constant = 0.0;

                    // Following call to setNeedsUpdateConstraints may not be necessary
                    [self.minimalView setNeedsUpdateConstraints];

                    [self.topView layoutIfNeeded];

                } completion:^(BOOL finished) {
                    ;
                }];

    // Other code to show full view
    // ...
}

小さなアクション スニペットのサイズを変更する

// An action to open our minimal view and hide our normal (full) view
- (IBAction)resizeSmallAction:(UIButton *)sender {

    [self.topView layoutIfNeeded];

    [UIView transitionWithView:self.minimalView
                  duration:1.0
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                    self.minimalViewHeightConstraint.constant = self.minimalViewFullHeight;
                    [self.minimalView setNeedsUpdateConstraints];

                    [self.topView layoutIfNeeded];

                } completion:^(BOOL finished) {
                    ;
                }];

        // Other code to hide full view
        // ...
    }

必要に応じて、transitionWithView の代わりに animateWithDuration を使用できます。

お役に立てれば。

于 2013-11-01T19:49:44.857 に答える