2013-10-15 6 views
9

UIDynamicAnimatorを使用して、すばらしい拡張/縮小アニメーションを実現する拡張可能なトレイビューのコードを作成しています。UIGravityBehaviorがアクティブなときにUIDynamicAnimatorが平衡に達することを拒否します。

現実的なアクセラレーションを実現するには、トレイの「タブ」が画面の下部に当たるまで、トレイを落ち着かせるためにUIGravityBehaviorを使用します。

これはうまくいきますが、シーン内のすべてのアイテムの移動が停止しても、UIDynamicAnimatorDelegate dynamicAnimatorDidPause:は呼び出されません。つまり、アニメータはCPUサイクルを使用してシーンをアニメーション化し続けます(デリゲートが設定され、UIDynamicAnimatorDelegate dynamicAnimatorDidPause:のために起動します)。

シーンからUIGravityBehaviorを取り除こうとしましたが、実際にアニメーターが最後に停止する原因となりました。私はすべての動きが止まったら、私はシーンからそれを削除する必要があるので、私は重力の動作の除去をすぐに時間を取ることができません。

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

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

誰も同じような問題がありますか?

+0

これを読んでいる人には、私が解決策を見つけた可能性があります。まだテストしていませんが、別の状況で同じ問題が発生しました。アニメーションブロック内でUIDynamicAnimatorのupdateItemUsingCurrentStateを使用していました。これは私のTrayViewクラスのケースではありませんでしたが、私はこの実現が将来の人々を助けるかもしれないと考えました。私が時間があれば、私はupdateItemUsingCurrentStateの使用状況を調べて、TrayViewクラスで問題が発生するのを止めることができるかどうかを調べます。 – Nailer

答えて

6

アニメーターは、すべてが休止すると一時停止するはずです。

あなたの重力の振る舞いに何が付いているかを確認し、他のアイテムがまだ落ちていないことを確認してください。例えば、誤って、次のバグを作成することは簡単です:

  • は重力
からビューを削除するにはスーパービューから、衝突
  • 失敗からビューを削除し、重力や衝突
  • にビューを追加します

    この状況では、 "ゴーストアイテム"は永遠に落ちます。

    あなたのアイテムが無限ではあるが小さな「バウンス」を引き起こしている他の動作にアタッチされている場合、別の可能性のある問題(あなたの説明はあまりありません)があります。私はあなたのアニメーターの行動の完全なリストをチェックします(子供の行動もチェックしてください)。特に、私はを追加するUIDynamicItemBehaviorに興味があります。


    EDIT:

    あなたはまた、他の道を行くことをお勧めします。非常に基本的なダイナミクスシステムから始め、問題を再現できるようになるまであなたのコンポーネントを追加してください。たとえば、次のように(「一時停止」のロギング)は非常に迅速に収束ん:

    @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はそのアイテムのすべてを直接認識していません。これは間接的にUIDyanamicBehavioritemsプロパティが含まれていないためです。これが私のことと同じくらいあなたを悩ましている場合は、radar://15054405を欺くことを検討してください。

    しかし、特定のアイテムの現在の線速度を知りたい場合は、解決策があります。

    UIDynamicItemBehavior *dynamicItemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[view]]; 
    __weak UIDynamicItemBehavior *weakBehavior = dynamicItemBehavior; 
    dynamicItemBehavior.action = ^{ 
        NSLog(@"Velocity: %@", NSStringFromCGPoint([weakBehavior linearVelocityForItem:view])); 
    }; 
    [self.animator addBehavior:dynamicItemBehavior]; 
    
  • +0

    私はまたあなたが言及している無限小バウンスを疑っています。私は弾力性のあるアイテムを取り除こうとしました。何らかの方法でアニメーターのアイテムの速度/加速度を印刷することは可能ですか? – Nailer

    +0

    詳細な編集をありがとう。私は間違いなく将来、バウンストレーを再訪する予定です。現在、私は以前のUIDynamics以前の実装に置き換えました。弾みのあるトレイは私の優先順位のリストでは今のところ最高ではありません;)私はあなたの答えを受け入れるでしょう。 – Nailer

    1

    私は最近同様の問題がありました。最後に、私は(それ以外の移動アイテムは、他にぶつかったので...)の代わりにアイテムの境界とUICollisionBehaviorを使用して、あなたが見つけた場合、私は重力

    UICollisionBehavior *collide = [[[UICollisionBehavior alloc] initWithItems:borders] retain]; 
    [collide addItem:movingItem]; 
    
    [collide setCollisionMode:UICollisionBehaviorModeBoundaries]; 
    [collide setTranslatesReferenceBoundsIntoBoundary:YES]; 
    

    を削除する必要があるときに知っているデリゲートメソッドcollisionBehavior:beganContactForItem:withBoundaryIdentifier:atPoint:を実装しますより良い解決策、私に教えてください:)!

    +0

    私はトレイを所定の位置に保持するために境界線を使用しています。 startedContactForItemに何かを追加する際の問題は、トレイが画面の一番下に達するとトレイが跳ね返ることです。したがって、最初のバウンスは重力を無効にし、ゼロ重力スタイルをバウンスするので、再び底を打つことはありません。 – Nailer

    +0

    そして、あなたが自分でアニメーションを完成させるために底に当たったときに、アニメータからアイテムを完全に削除したら?または、アイテムが1つしかない場合は、 'dynamicAnimatorDidPause:'がトリガされたときに正しくアニメーションに置き換えることができますか? – KIDdAe

    +0

    'dynamicAnimatorDidPause:'決してトリガされませんが、最初の衝突後に手動でアニメーションを終了させることが1つの解決策である可能性があります。 – Nailer

    1

    この問題を解決するには、UIDynamicItemBehaviorにカスタムアクションを追加してください。私のアニメーターは決して安静になることはありません。私のアプリは3〜4%のCPUを永久に消費します。私の見解はすべて1/2秒以内に動くのをやめているようです。だから私が平衡に達していない理由を理解するのではなく、ちょうどハンマーでそれを打ち、タイマーでアニメーターを殺す。私はそれに2秒を与える。

    - (void)createAnimator { 
        if (_timer) { 
         [_timer invalidate]; 
        } 
    
        if (_animator) { 
         [_animator removeAllBehaviors]; 
        } 
    
        _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; 
    
        // create all behaviors 
    
        // kill the animator in 2 seconds 
        _timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(killAnimator:) userInfo:nil repeats:NO]; 
    } 
    
    - (void)killAnimator:(NSTimer *)timer { 
        [_animator removeAllBehaviors]; 
        _animator = nil; 
        _timer = nil; 
    } 
    
    関連する問題