9

私は、UIDynamicAnimator を使用して拡張/縮小アニメーションを実現する拡張可能なトレイ ビューのコードに取り組んでいます。

現実的な加速を実現するためにUIGravityBehavior、トレイの「タブ」が画面の下部に当たるまで、トレイを落下させるために使用します。

これはうまく機能しますが、シーン内のすべてのアイテムの動きが停止しても、UIDynamicAnimatorDelegate dynamicAnimatorDidPause:が呼び出されることはありません。これは、アニメーターが引き続き CPU サイクルを使用してシーンをアニメートすることを意味します (デリゲートが設定され、 に対して発火しますUIDynamicAnimatorDelegate dynamicAnimatorDidPause:)。

シーンからを削除しようとしUIGravityBehaviorましたが、最終的にアニメーターが停止しました。ただし、すべての動きが止まったらシーンから削除する必要があるため、重力の動作を削除するタイミングが適切ではありません。

重力が一定の力であることは理解していますが、すべての速度と加速度が 0 になるとアニメーターは停止すると想定していました。

この最後の仮定は間違っていますか?

同様の問題を抱えている人はいますか?

4

3 に答える 3

6

すべてが落ち着いたら、アニメーターが一時停止する必要があるというあなたの意見は正しいです。

重力の動作に何itemsが関連付けられているかを確認し、他のアイテムがまだ落下していないことを確認してください。たとえば、次のバグを誤って作成するのは簡単です。

  • 重力と衝突にビューを追加する
  • スーパービューと衝突からビューを削除
  • 重力からビューを削除できません

このままでは「ゴーストアイテム」が永遠に落ちてしまいます。

もう 1 つの考えられる問題 (あなたの説明を考えると可能性は低いですが) は、あなたのアイテムが、無限ではあるが小さい「バウンス」を引き起こしている他の動作に関連付けられている場合です。アニメーターの動作の完全なリストを確認します (子の動作も確認することを忘れないでください)。UIDynamicItemBehavior特に、追加するものに興味がありますelasticity


編集:

また、別の方法で移動することもできます。非常に基本的なダイナミクス システムから始めて、問題が再現できるようになるまでコンポーネントを追加します。たとえば、次の例は非常に迅速に収束します (「一時停止」のログ)。

@interface PTLViewController () <UIDynamicAnimatorDelegate>
@property (nonatomic, strong) UIDynamicAnimator *animator;
@end

@implementation PTLViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100,100,100,100)];
  view.backgroundColor = [UIColor lightGrayColor];
  [self.view addSubview:view];

  self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
  self.animator.delegate = self;

  UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[view]];
  collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
  [self.animator addBehavior:collisionBehavior];

  UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[view]];
  [self.animator addBehavior:gravityBehavior];
}

- (void)dynamicAnimatorDidPause:(UIDynamicAnimator *)animator {
  NSLog(@"pause");
}
@end

すべてのアイテムの速度を取得することについてのあなたの質問に対して、私はそれを行う簡単な方法を知りません. 残念ながら、UIDynamicAnimatorすべてのアイテムを直接知っているわけではありません。プロパティUIDyanamicBehaviorが含まれていないため、これは間接的です。itemsこれが私と同じくらい気になる場合は、レーダー://15054405 を複製することを検討してください。

ただし、特定のアイテムの現在の線速度を知りたいだけの場合は、解決策があります。UIDynamicItemBehaviorログに記録するカスタム アクションを追加するだけです。

UIDynamicItemBehavior *dynamicItemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[view]];
__weak UIDynamicItemBehavior *weakBehavior = dynamicItemBehavior;
dynamicItemBehavior.action = ^{
  NSLog(@"Velocity: %@", NSStringFromCGPoint([weakBehavior linearVelocityForItem:view]));
};
[self.animator addBehavior:dynamicItemBehavior];
于 2013-10-15T16:16:42.080 に答える