NSBlogger

意識高いブログ

UIGravityBehaviorとUICollisionBehaviorでバウンドする開閉メニューをつくる

UIGravityBehavior

UIViewに重力を与えることができます。重力を与える方向や強さの調整も可能。

UICollisionBehavior

UIViewが衝突したときの挙動を与えられます。ここのラインにきたらバウンドさせるという動きができます。

事前準備

@property (nonatomic, strong) UIDynamicAnimator *animator;
@property (nonatomic, strong) UIView *menuView;

UIDynamicAnimatorのプロパティを作っておきます。このプロパティがアニメーションを制御してくれます。
menuViewにはボタンをおしたら上から落ちてきて一定のラインでバウンドして止まる動きをつけます。

落下させたいViewに重力を与える

UIGravityBehavior *gravityBeahvior = [[UIGravityBehavior alloc] initWithItems:@[self.menuView]];
gravityBeahvior.magnitude = 3.0;
[self.animator addBehavior:gravityBeahvior];

落下させたいViewをinitWithItemsで指定し、UIGravityBehaviorを作成します。
magnitude」で力加減を調整できます。
「animator」に「addBehavior」すれば重力を与えるビヘイビアの登録が完了です。
ちなみにこれだけだと、下にすーっと落下していきます。
UIGravityBehaviorには「angle」というプロパティがあり、ここでどの方向に重力を与えるか指定できます。

バウンドさせる場所を指定する

CGFloat collisionLine = 150;            
UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[self.menuView]];
[collisionBehavior addBoundaryWithIdentifier:@"bottom" fromPoint:CGPointMake(0, collisionLine) toPoint:CGPointMake(self.view.bounds.size.weight, collisionLine)];
[self.animator addBehavior:collisionBehavior];

「collisionLine」で衝突させる位置を指定します。
上記の設定だと(0, 150)と(320, 150)をつなぐラインで衝突させることができます。
高さを調整して、Tabbarの真上とかに設定すると、上から落ちてきたメニューがTabbarのちょうど真上でバウンドして止まるようになります。

dynamicAnimatorDidPause でアニメーションが終わった瞬間をキャッチ

「UIDynamicAnimatorDelegate」に以下のふたつのメソッドがあります。

  • dynamicAnimatorWillResume
    • アニメーションが再開するときに呼ばれる
  • dynamicAnimatorDidPause
    • アニメーションが終わったときに呼ばれる

基本的にビヘイビアをaddしたら、それをremoveするまでずっとビヘイビアが有効です。
上記の例だと、指定したラインでバウンドして止まったらアニメーションが一旦終了になり、「dynamicAnimatorDidPause」が呼ばれますが、またself.menuViewが上のほうに移動すると落下します(常に重力がかかっているといるので)。こういった、もう一度アニメーションが再開するときに呼ばれるのが「dynamicAnimatorWillResume」です。

- (void)dynamicAnimatorDidPause:(UIDynamicAnimator *)animator{
    [self.animator removeAllBehaviors];
}

1回ビヘイビアの動作が終了したら繰り返さなくてもいいやっていうときは、ビヘイビアを忘れずにremoveしておきます。
また動作させたいときにビヘイビアをaddすれば同様に動きます。

まとめ

UIGravityBehaviorでUIViewに重力を与え、UICollisionBehaviorで指定した位置で衝突させることができます。メニューの動きにちょっとした仕掛けを施したいときに簡単につかえるのでぜひ。