制約の変更をアニメーション化するにはどうすればいいですか? 質問する

制約の変更をアニメーション化するにはどうすればいいですか? 質問する

古いアプリを更新しているのですがAdBannerView、広告がないときは画面からスライドして消えます。広告があるときは画面上にスライドして表示されます。基本的なことです。

古いスタイルでは、アニメーション ブロックにフレームを設定していました。新しいスタイルIBOutletでは、位置を決定する自動レイアウト制約 (Yこの場合はスーパービューの下部からの距離) を設定し、定数を変更します。

- (void)moveBannerOffScreen {
    [UIView animateWithDuration:5 animations:^{
        _addBannerDistanceFromBottomConstraint.constant = -32;
    }];
    bannerIsVisible = FALSE;
}

- (void)moveBannerOnScreen {
    [UIView animateWithDuration:5 animations:^{
        _addBannerDistanceFromBottomConstraint.constant = 0;
    }];
    bannerIsVisible = TRUE;
}

バナーは予想通り動きますが、アニメーションは表示されません


更新:再視聴しましたWWDC 12 講演 自動レイアウトをマスターするためのベストプラクティスアニメーションについて説明しています。CoreAnimationを使用して制約を更新する方法について説明します。

次のコードを試してみましたが、まったく同じ結果が得られました。

- (void)moveBannerOffScreen {
    _addBannerDistanceFromBottomConstraint.constant = -32;
    [UIView animateWithDuration:2 animations:^{
        [self.view setNeedsLayout];
    }];
    bannerIsVisible = FALSE;
}

- (void)moveBannerOnScreen {
    _addBannerDistanceFromBottomConstraint.constant = 0;
    [UIView animateWithDuration:2 animations:^{
        [self.view setNeedsLayout];
    }];
    bannerIsVisible = TRUE;
}

ちなみに、何度も確認したところ、これはメインスレッドで実行されています。

ベストアンサー1

2 つの重要な注意事項:

  1. layoutIfNeededアニメーションブロック内で呼び出す必要があります。Appleは、保留中のレイアウト操作がすべて完了していることを確認するために、アニメーションブロックの前に1回呼び出すことを推奨しています。

  2. 制約がアタッチされている子ビューではなく、親ビュー(例self.view)で具体的に呼び出す必要があります。これを行うと、制約を変更したビューに制約されている可能性のある他のビューのアニメーション化を含め、すべての制約ビューが更新されます (例: ビュー B はビュー A の下部にアタッチされており、ビュー A の上部オフセットを変更したので、ビュー B をそれに合わせてアニメーション化したい場合)。

これを試して:

オブジェクティブC

- (void)moveBannerOffScreen {
    [self.view layoutIfNeeded];

    [UIView animateWithDuration:5
        animations:^{
            self._addBannerDistanceFromBottomConstraint.constant = -32;
            [self.view layoutIfNeeded]; // Called on parent view
        }];
    bannerIsVisible = FALSE;
}

- (void)moveBannerOnScreen { 
    [self.view layoutIfNeeded];

    [UIView animateWithDuration:5
        animations:^{
            self._addBannerDistanceFromBottomConstraint.constant = 0;
            [self.view layoutIfNeeded]; // Called on parent view
        }];
    bannerIsVisible = TRUE;
}

スイフト3

UIView.animate(withDuration: 5) {
    self._addBannerDistanceFromBottomConstraint.constant = 0
    self.view.layoutIfNeeded()
}

おすすめ記事