はじめに
Android アプリにおける画面遷移は主に
- Activity による画面遷移
- Jetpack Navigation を用いた Fragment による画面遷移
- Compose を使用したナビゲーション
がありますが、この記事では Jetpack Navigation による画面遷移のアニメーションについて述べます。Jetpack Naviation は Compose 登場前から開発しているアプリでは、現在でも使われているケースが多いと思います。
Jetpack Navigation による画面遷移は設定しなければアニメーションなし
Jetpack Navigation では XML で画面遷移を定義しますが、それだけでは画面遷移がカットインになっていしまい不自然です。
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph"
app:startDestination="@+id/screen1">
<fragment
android:id="@+id/screen1"
android:name="com.tfandkusu.ate.feature.jnta.Screen1Fragment">
<action
android:id="@+id/actionScreen2"
app:destination="@+id/screen2" />
</fragment>
<fragment
android:id="@+id/screen2"
android:name="com.tfandkusu.ate.feature.jnta.Screen2Fragment" />
</navigation>
// Screen1Fragment から Screen2Fragment に遷移する
findNavController().navigate(
Screen1FragmentDirections.actionScreen2(),
)
ナビゲーション グラフ XML にアニメーションを設定する
ナビゲーション グラフ XML の action タグにアニメーションを設定することができます。
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph"
app:startDestination="@+id/screen1">
<fragment
android:id="@+id/screen1"
android:name="com.tfandkusu.ate.feature.jnta.Screen1Fragment">
<!-- アニメーション追加 -->
<action
android:id="@+id/actionScreen2"
app:destination="@+id/screen2"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />
</fragment>
<fragment
android:id="@+id/screen2"
android:name="com.tfandkusu.ate.feature.jnta.Screen2Fragment" />
</navigation>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="400"
android:fromXDelta="100%p"
android:toXDelta="0" />
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="400"
android:fromXDelta="0"
android:toXDelta="-100%p" />
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="400"
android:fromXDelta="-100%p"
android:toXDelta="0" />
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="400"
android:fromXDelta="0"
android:toXDelta="100%p" />
</set>
今回は左右にスライドする画面遷移のアニメーションを設定しました。
疑問
ところで、このアニメーションは Android として自然、言い換えると Material Design に沿ったアニメーションなのでしょうか。次の節からは Material Design の公式サイト https://m3.material.io/ を読んで、それに沿ったアニメーションを設定します。
Material Design に沿って画面遷移アニメーションを設定する
Material Design の公式サイト https://m3.material.io/ の Styles → Motion → Transitions に画面遷移アニメーションのガイドラインがありました。
最初に Container transform という、共通要素の View を使って自然な画面遷移をする別名 Shared element transition に言及していますが、今回はその次の Forward and backward を設定します。
Forward and backward には、アニメーション動画とともに Android implementation というリンクがあるので、そこに飛びます。
Shared axis という節でアニメーションの設定方法を解説しているので、同じように設定します。
// 画面遷移アニメーションを設定する
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
// Screen3Fragment に遷移する
findNavController().navigate(Screen1FragmentDirections.actionScreen3())
class Screen3Fragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 画面遷移アニメーションを設定する
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
}
// 略
}
Forward and backward の解説通りのアニメーションが設定できました。
まとめ
この記事では画面遷移に Jetpack Navigation を使っているケースで、 Material Design で紹介されている Forward and backward アニメーションの設定方法を解説しました。
例えば、iOS の画面遷移に寄せる形で Android 側は独自にアニメーションを設定していたが、やっぱり Android アプリは Android らしさを追求したい場合は、今回紹介した Material Design のサイトを参考にして Android らしい画面遷移アニメーションを設定することができます。
iOSの画面遷移アニメーションの例