私はUIView
すべてを使用して配置された一連のサブビューを持っていlayoutSubviews
ます。のview
サイズを変更すると、相対位置がすべて変更されます。アニメーションのサイズ変更中にこれらの再計算が行われるようにしたいと思います (+[UIView beginAnimations:]
呼び出しを使用)。これは起こっていないようです。何か案は?
4 に答える
前提: 複数のアニメーション ステップが必要です (つまり、位置がフレーム サイズに比例して変化しない)。
これは、単一の「標準」UIView アニメーションでは不可能です。なんで?フレーム/境界は一度だけ設定されます。
Core Animationには 3 つの「レイヤー ツリー」があります。
- モデル ツリーは、アプリが認識している場所です。
- プレゼンテーション ツリーは、ほぼ画面に表示されているものです。
- レンダー ツリーは、ほぼ Core Animation が合成しているものです。
UIView は、モデル レイヤーの (やや薄い) ラッパーです。UIView アニメーション中、コア アニメーションはプレゼンテーション/レンダリング ツリーを更新します — モデル ツリーはアニメーションのエンドポイントを表します。要するに、コードは (ほとんどの場合) アニメーションを瞬間的なものとして扱うことができるということです。つまり、ビューを A から B に移動すると、すぐに B に移動します。変更はたまたまユーザーにアニメーション化されます。
CALayer/CAAnimation を直接使用すると、もっと複雑なことができますが、これについてはあまり調査していません。
-[UIView setAnimationDidStopSelector:] を使用して、複数のアニメーションを連鎖させることができます。(複数のアニメーションを setAnimationDelay: と一緒に使用することもできますが、同じプロパティで複数のアニメーションを使用するとどうなるかはわかりません。setAnimationBeginsFromCurrentState: でうまくいくかもしれません。)
本当にきめ細かい制御が必要な場合は、CADisplayLink (OS 3.1+) は、画面が更新されるたびに起動するタイマーです。フォールバック オプション (3.0 サポート用) は、30/60 Hz 程度で NSTimer を使用することです。
これは古い質問であることは知っていますが、このコードは私にとって非常にうまく機能します(フレームを変更する例に適しています)。
-(void)layoutSubviews{
[super layoutSubviews];
// layout your subviews here, or whatever
}
-(void)someMethod{
double duration=...;
[UIView animateWithDuration:duration animations:^{
self.frame = ...;
[self layoutIfNeeded];
}];
}
もちろん、このメソッドを別のオブジェクトから呼び出すこともできます。「トリック」は、layoutIfNeeded(または直接layoutSubviews - setNeedsLayoutが呼び出されるフレームを変更した場合と同じこと)を呼び出すことです。
tcとして。「レイヤーツリー」をうまく説明しました。プレゼンテーションレイヤーに、モデルレイヤーの最終段階をアニメーションで表示させるだけです。
この方法の利点は、フレーム/境界の変更がいつアニメーション化され、いつ瞬時に変更されるかを制御できることです。
これが誰かに役立つことを願っています:)。
完全を期すために投稿します。tcさんありがとうございます。私がやりたいことは、正確には Core Animation ではサポートされていないことを説明してくれました。
私は最終的に合理的な解決策を思いつきました。サブビューを -layoutSubviews でレイアウトするのではなく、-setBounds: でレイアウトします。次に、-setBounds: 呼び出しを UIView +beginAnimations: ブロックでラップすると、これらの位置決め呼び出しもアニメーション化され、最終結果は、すべてが適切にアニメーション化され、本来あるべき場所に移動します。