AndroidでActivity切り替え時にアニメーションしたい

AndroidでActivity切り替え時にアニメーションさせたくて調べてたんですが、ややこしくてだいぶ混乱しました。 Androidはもともとアニメーション周りが弱くて、バージョンが上がるたびに違ったやり方で強化した結果、統一感がなくなってる印象。
全貌を解き明かす気はないので、今回は「Activity切り替え時に比較的シンプルなアニメーションを適用する」ことに絞って調べてみました。ターゲットはAndroid4系以降です。
とりあえず分かったこと。
- アニメーションの指定は「次に表示するActivityの出現用」「いま表示しているActivityの消失用」の2つがセット
- startActivity()やfinish()の後にoverridePendingTransition(int enterAnim, int exitAnim)を呼ぶのが昔ながらのやり方
- themeとしてアニメーションを指定することもできる
- アニメーションの中身(どのようなアニメーションをするか)はxmlで定義するのが王道
overridePendingTransitionだとハードコーディングになるのでtheme化するのがよさそうです。
<!-- Activityをアニメーションさせるためのstyle -->
<style name="Animation.Standard" parent="android:Animation.Activity">
<item name="android:activityOpenEnterAnimation">@anim/fade_in</item>
<item name="android:activityOpenExitAnimation">@anim/fade_out</item>
<item name="android:activityCloseExitAnimation">@anim/fade_out</item>
<item name="android:activityCloseEnterAnimation">@anim/fade_in</item>
</style>
<!-- styleが適用されたtheme -->
<style name="AnimatedTheme" parent="AppTheme">
<item name="android:windowAnimationStyle">@style/Animation.Standard</item>
</style>
OpenEnterとOpenExitがActivity表示時、CloseExitとCloseEnterがActivity消失時ですね。それぞれに今のActivityと次のActivityがあるので合計4つ指定することになります。
あとはAndroidManifest.xmlでApplication全体なりActivity個別なりにAnimatedThemeを適用すればOK、のはずだったんですが、ここで落とし穴が。試してみたらActivityの消失時アニメーションが適用されません。
Why my close activity animation doesn’t work on Android 4.0 (ICS) - Stack Overflow
どうやらICSのバグっぽい。C Jamesさんが提示してくれているworkaroundほぼそのままですが、以下のようなコードを書いたら無事動くようになりました。
private int closeEnterAnimationId;
private int closeExitAnimationId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
TypedArray activityStyle = getTheme().obtainStyledAttributes(new int[]{android.R.attr.windowAnimationStyle});
int windowAnimationStyleResId = activityStyle.getResourceId(0, 0);
activityStyle.recycle();
activityStyle = getTheme().obtainStyledAttributes(windowAnimationStyleResId, new int[]{android.R.attr.activityCloseEnterAnimation, android.R.attr.activityCloseExitAnimation});
closeEnterAnimationId = activityStyle.getResourceId(0, 0);
closeExitAnimationId = activityStyle.getResourceId(1, 0);
activityStyle.recycle();
}
@Override
public void finish() {
super.finish();
overridePendingTransition(closeEnterAnimationId, closeExitAnimationId);
}
Material Designっぽいアニメーションなど、もっと凝ったことをしようとするとActivity Transitionsやらなにやらが必要になってきますが、シンプルに画面全体をアニメーションするのであれば今回の内容で事足りるはず。
関連(するかもしれない)記事
おススメ