[iOS 7] お手軽になったキーフレームアニメーション!

iOS 7からUIKitにキーフレームアニメーションが加わった!

iOS6まではキーフレームアニメーションを実現するにはUIKitによるアニメーションよりちょいと複雑なCore AnimationのCAKeyframeAnimationを使っていましたが、iOS 7からUIKitだけでキーフレームアニメーションが実装できるようになりました!

UIKitによるアニメーション vs Core Animation

まず、UIKitによるアニメーションとCore Animationで何が違うのかをおさらいしておきましょう。

UIKitによるアニメーションは、Core Animationを直接実装するよりも比較的簡単です。以下のサンプルコードを見てみましょう。
以下のコードはビューの背景色を徐々に赤から青に変更するアニメーションをそれぞれ実現しています。

// UIKitによるアニメーション
[UIView animateWithDuration:1.0f
                 animations:^{
                     view.backgroundColor = [UIColor blueColor];
                 }];

// Core Animation
CABasicAnimation *animation = [CABasicAnimation animation];
animation.duration = 1.0f;
animation.toValue = (id)[UIColor blueColor].CGColor;
[view.layer addAnimation:animation forKey:@"backgroundColor"];

見て分かる通り、UIKitによるアニメーションの方がObjective-Cっぽくてより直感的に書けます。実は、UIKitによるアニメーションは、Core Animationがよくわからない開発者でも手軽にアニメーションを実現可能にするために用意されたもので、実際はUIkitによるアニメーションも内部的にはCore Animationが実行されています。そのため、ある程度簡単なアニメーションであればUIKitによるアニメーションでお手軽に実装できます。
反面、UIKitによるアニメーションではCore Animationを直接実装したものより複雑なアニメーションが実現できないというデメリットがあります。

要するに、お手軽さにアニメーションしたいときはUIKitによるアニメーション、複雑でより負荷のかからないようにアニメーションしたいときはCore Animation、ってな感じです。

そんなiOSのアニメーションですが、iOS6まではキーフレームアニメーションを実現するにはCore AnimationのCAKeyframeAnimationしか用意されていませんでした。
そして今回iOS 7より新たに追加されたのがUIKitによるキーフレームアニメーションってわけです!

UIKitによるキーフレームアニメーション

それではようやく本題です。iOS 7からUIKitによるキーフレームアニメーションを実現するためのメソッドとして以下の2つが追加されました。

  • animateKeyframesWithDuration:delay:options:animations:completion:
  • addKeyframeWithRelativeStartTime:relativeDuration:animations:

これらのメソッドの使い方は文章で説明するより、実際にソースコードを書いて動かした方が手っ取り早いです。実際のソースを見てみましょう。Single View Applicationプロジェクトを作成し、以下のようにViewController.mにviewDidAppear:を実装してみましょう。

ViewController.m

・・・

@implementation ViewController

・・・

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    /*
     背景色を徐々に変更する
     */

    // アニメーションさせるビューを追加
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100.0f, 100.0f, 120.0f, 120.0f)];
    view.backgroundColor = [UIColor redColor]; // 初期表示は赤色
    [self.view addSubview:view];

    // 2秒間キーフレームアニメーションを実行する(逆再生&リピート)
    [UIView animateKeyframesWithDuration:2.0
                                   delay:0.0
                                 options:UIViewKeyframeAnimationOptionAutoreverse | UIViewKeyframeAnimationOptionRepeat
                              animations:^{
                                  // 0.8秒間(2.0 * 0.4)かけて背景を黄色に
                                  [UIView addKeyframeWithRelativeStartTime:0.0
                                                          relativeDuration:0.4
                                                                animations:^{
                                                                    view.backgroundColor = [UIColor yellowColor];
                                                                }];

                                  // 0.8秒間(2.0 * 0.4)後に1.2秒間(2.0 * 0.6)かけて背景を緑色に
                                  [UIView addKeyframeWithRelativeStartTime:0.4
                                                          relativeDuration:0.6
                                                                animations:^{
                                                                    view.backgroundColor = [UIColor greenColor];
                                                                }];
                              } completion:NULL];
}

・・・

@end

このソースを実行すると、画面に配置したビューの背景色が赤、黄色、緑にアニメーションするはずです。

ios7-keyframeanimation-1

animateKeyframesWithDuration:delay:options:animations:completion:メソッド

このメソッドはなんか見たことある気がしますね。そうです、iOS 6まででもよく利用していたanimateWithDuration:delay:options:animations:completion:です。animateKeyframesWithDuration:delay:options:animations:completion:animateWithDuration:delay:options:animations:completion:とほぼ同じように動作します。例えば、以下のように書いても動作します。

[UIView animateKeyframesWithDuration:2.0
                               delay:0.0
                             options:UIViewKeyframeAnimationOptionAutoreverse | UIViewKeyframeAnimationOptionRepeat
                          animations:^{
                              view.backgroundColor = [UIColor yellowColor];
                          } completion:NULL];
}

どうやってUIKitによるキーフレームアニメーションを実現するのか?
そこで登場するのがもう1つのメソッド、addKeyframeWithRelativeStartTime:relativeDuration:animations:メソッドです!

addKeyframeWithRelativeStartTime:relativeDuration:animations:メソッド

addKeyframeWithRelativeStartTime:relativeDuration:animations:animateKeyframesWithDuration:delay:options:animations:completion:で指定された秒数の中でどのタイミングで(relativeStartTime)、どのくらいの秒数(relativeDuration)アニメーションするかを相対的に指定するためのメソッドです。

実はこのaddKeyframeWithRelativeStartTime:relativeDuration:animations:はそもそも単独で使用できません。 animateKeyframesWithDuration:delay:options:animations:completion:のアニメーションブロック内で初めて効果の出るメソッドなのです!

ここで特に重要なのが、指定する時間に関する値はあくまで相対的な値であることです。指定できる値は0〜1.0です。
例えばanimateKeyframesWithDuration:delay:options:animations:completion:でアニメーション時間が5秒だとすると、0.1を指定すれば0.5秒0.5を指定すれば2.5秒になります。分かってしまえば非常に簡単ですね。

実際使ってみた感想

確かにObjective-Cらしく使える点ではCore Animationでキーフレームアニメーションを実装するよりスッキリ見えますが、ソースコードの量はそんな変わらないし、かゆいところに手が届かないので、慣れている人はCore Animationやる方がいいです。使いどころとしてはホントにちょっとしたところだけって感じでしょうか?適度に使い分けましょう!