overridePendingTransition
がDeprecatedになったけど、SDK_INT
で分岐させてoverridePendingTransition
を単純にoverrideActivityTransition
に置き変えればよい訳ではない。というお話
前置き
長らくActivity遷移アニメーションを指定するために使っていた Activity#overridePendingTransition
がDeprecatedになってしまいました。
This method was deprecated in API level 34.
Use overrideActivityTransition(int, int, int)} instead.
ということで overrideActivityTransition
に置き換えなさいということですね。
overrideActivityTransition
の説明には以下のように書かれています。
For example, if we want to customize the opening transition when launching Activity B which gets started from Activity A, we should call this method inside B's onCreate with overrideType = OVERRIDE_TRANSITION_OPEN because the Activity B will on top of the task. And if we want to customize the closing transition when finishing Activity B and back to Activity A, since B is still is above A, we should call this method in Activity B with overrideType = OVERRIDE_TRANSITION_CLOSE.
ようするに、AからBに遷移するときのアニメーションと、BからAに戻るときのアニメーションはBで指定しなさい。ってことらしいです。AからBに遷移するときのアニメーションはBのonCreateで指定しなさい。ってことです。
つまり、overridePendingTransitionを単純にoverrideActivityTransitionに置き変えればよい訳ではないってことみたいです。
ちょっと検証してみましょう。
検証
遷移アニメーションが分かりやすいように以下のようなアニメーションリソースを定義しておきます。
アニメーションリソース
<?xml version="1.0" encoding="utf-8"?>
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXDelta="-100%"
android:toXDelta="0%"
/>
<?xml version="1.0" encoding="utf-8"?>
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXDelta="100%"
android:toXDelta="0%"
/>
<?xml version="1.0" encoding="utf-8"?>
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXDelta="0%"
android:toXDelta="-100%"
/>
<?xml version="1.0" encoding="utf-8"?>
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXDelta="0%"
android:toXDelta="100%"
/>
duration
を1000=1秒と長めに設定して、違いが分かりやすいようにしています。
overridePendingTransition
MainActivityとMainActivity2の間で遷移させるとして、overridePendingTransition
は以下のように使いますね。
binding.button.setOnClickListener {
startActivity(Intent(this, MainActivity2::class.java))
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left)
}
binding.button.setOnClickListener {
finish()
overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right)
}
こうすることで、MainActivityからMainActivity2の遷移とその戻りのアニメーションをカスタマイズすることができます。これはAndroid 14でもまだ使えますね。
デフォルト | overridePendingTransition |
---|---|
単純に置き換え
先に説明したとおり、単純な置き換えはできないということでしたが、置き換えた場合どうなるのかを見てみましょう。
binding.button.setOnClickListener {
startActivity(Intent(this, MainActivity2::class.java))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
overrideActivityTransition(
Activity.OVERRIDE_TRANSITION_OPEN, R.anim.slide_in_right, R.anim.slide_out_left
)
} else {
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left)
}
}
binding.button.setOnClickListener {
finish()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
overrideActivityTransition(
Activity.OVERRIDE_TRANSITION_CLOSE, R.anim.slide_in_left, R.anim.slide_out_right
)
} else {
overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right)
}
}
そうすると以下のように、finish
のあととはいえ、MainActivity2の方で指定したクローズのアニメーションは適用されていますが、MainActivityの方で指定した、オープンのアニメーションは適用されませんでした。
overridePendingTransition | overrideActivityTransition |
---|---|
正しい対応方法
上に表示されるActivityのonCreateでOPEN/CLOSEとも指定するのが良さそうです。
CLOSEも指定するのは、overridePendingTransition
と違って先に指定しておけるためであることと、後述しますが、予測型「戻る」ジェスチャーの挙動に影響するためです。
複数回呼び出した場合は上書きになるため、閉じ方によってアニメーションを変更したい場合はその直前に指定すれば変更できますし、clearOverrideActivityTransition
という指定をクリアするメソッドも用意されています。
binding.button.setOnClickListener {
startActivity(Intent(this, MainActivity2::class.java))
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
overrideActivityTransition(
Activity.OVERRIDE_TRANSITION_OPEN, R.anim.slide_in_right, R.anim.slide_out_left
)
overrideActivityTransition(
Activity.OVERRIDE_TRANSITION_CLOSE, R.anim.slide_in_left, R.anim.slide_out_right
)
}
val binding = ActivityMain2Binding.inflate(layoutInflater)
setContentView(binding.root)
binding.button.setOnClickListener {
finish()
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right)
}
}
}
overridePendingTransition | overrideActivityTransition |
---|---|
予測型「戻る」ジェスチャーの挙動
overrideActivityTransition
でOVERRIDE_TRANSITION_CLOSE
の指定をすると、Android 14から導入された、予測型「戻る」ジェスチャーでの動きにも適用されます。このアニメーションはfinishの前に実行されるものなので、このタイミングではなく、あらかじめ設定しておく必要があります。
overridePendingTransition | overrideActivityTransition |
---|---|
まとめ
予測型「戻る」ジェスチャーのアニメーションの指定もできるようになっているので、overrideActivityTransition
への置き換えを進めていきたいですね。ただ、単純な置き換えはできないので、minSdkVersionを34にできるまでは、処理の分岐をあちこちで書かないといけないのが悩みどころですね。
overrideActivityTransitionが使えない場合
これで万事解決かと思いきや、overrideActivityTransition
が通用しない場合がありました。
Activityのテーマで、android:windowShowWallpaper
やandroid:windowIsTranslucent
をtrue
にしている場合です。
<style name="Theme.MyApplication2" parent="Base.Theme.MyApplication">
<item name="android:windowShowWallpaper">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
この場合、以下のように、overridePendingTransition
では指定できるのに、overrideActivityTransition
では指定とは異なるアニメーションになってしまいます。(予測型「戻る」ジェスチャーには適用されるみたいですが……)
overridePendingTransition | overrideActivityTransition |
---|---|
ActivityOptionを使う方法
開始についてはstartActivityのActivityOptionについてはまだDeprecatedになっていませんので、以下のようにするとこで開始アニメーションを変更できます。
val options = ActivityOptions.makeCustomAnimation(this, R.anim.slide_in_right, R.anim.slide_out_left).toBundle()
startActivity(Intent(this, MainActivity2::class.java), options)
しかし、閉じる方のアニメーションはこのような方法では指定できないようです。
wallpaperXXXXAnimation を指定する方法
オープンクローズ両方を指定したい場合は、以下のようにstyleを作成し
<style name="anim">
<item name="android:wallpaperOpenEnterAnimation">@anim/slide_in_right</item>
<item name="android:wallpaperOpenExitAnimation">@anim/slide_out_left</item>
<item name="android:wallpaperCloseEnterAnimation">@anim/slide_in_left</item>
<item name="android:wallpaperCloseExitAnimation">@anim/slide_out_right</item>
</style>
window.setWindowAnimations
でActivityで指定します。
window.setWindowAnimations(R.style.anim)
こうすることで、同様のアニメーションを実行することができるようになりました。
以上です。