風景の中の巨大なキーボードでブロックされるように、いくつかのビューをアニメーション化しようとしています。フレームを単純にアニメーション化すればうまくいきますが、他の人はこれが逆効果であると示唆しており、代わりにNSLayoutConstraintsを更新する必要があります。ただし、それらはアニメート可能ではないようです。誰かが彼らを成功に導いてくれましたか?
//heightFromTop is an NSLayoutConstraint referenced from IB
[UIView animateWithDuration:0.25 animations:^{
self.heightFromTop.constant= 550.f;
}];
その結果、問題の高さに瞬時にジャンプします。
次の正確なパターンに従ってください。
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()
})
Appleの提案する方法は少し異なります( 「自動レイアウトによる変更のアニメーション化」セクションの例を参照 )。最初に、アニメーションの前にlayoutIfNeededを呼び出す必要があります。次に、アニメーションブロック内にアニメーションを追加し、最後に再度layoutIfNeededを呼び出します。自動レイアウトに移行している私のような人にとっては、アニメーションブロック内のフレームで行っていた以前のアニメーションに似た方法です。 layoutIfNeededを2回呼び出すだけです-アニメーションの前とアニメーションの後に:
[self.view layoutIfNeeded]; // Ensures that all pending layout operations have been completed
[UIView animateWithDuration:1.0f animations:^{
// Make all constraint changes here
self.heightFromTop.constant= 550.f;
[self.view layoutIfNeeded]; // Forces the layout of the subtree animation block and then captures all of the frame changes
}];
@Centurionのアプローチを試しましたが、ストーリーボードから読み込まれた場合、どういうわけか私のビューは間違ったフレームにアニメーション化されます。最初のlayoutIfNeeded
をupdateConstraintsIfNeeded
に置き換えると、問題はなくなりますが、理由はわかりません。誰もが説明をすることができれば、それは大歓迎です。
[self.view updateConstraintsIfNeeded];
[UIView animateWithDuration:1.0 animations:^{
self.myConstraint.constant= 100;
[self.view layoutIfNeeded];
}];
私は同様の問題を抱えていましたが、このスレッドはそれを乗り越えるのに非常に役立ちました。
エルレイノンからの答えは私を正しい道に導きましたが、少し違う答えを提案したいと思います。アニメートされたトランジションの代わりにジャンプがまだあったので、エルレイノンからの推奨コードは私には機能しませんでした。 cnotethegr8が提供するリンクは、実際の答えを提供してくれました。
自動レイアウトガイドhttps://developer.Apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/AutoLayoutbyExample/AutoLayoutbyExample .html (ページの一番下まで)。
エルライノンによる回答とのいくつかの違い:
これは、上記のリンクの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を使用できます。
お役に立てれば。