📱

Android:Activity間のページ遷移にトランジションアニメーションを適用する+ハマってしまったポイント

2022/10/10に公開

はじめに

Activity間のページ遷移の際に、トランジションアニメーションをつけました。
そのトランジションアニメーションのつけ方と、その際にハマってしまったポイントがあるので紹介します。サンプルコードは下記のような動作をします。

トランジションアニメーションのつけかた

サンプルコードでは、下記のようなディレクトリ構造になっています。

サンプルコードではActivity_1、Activity_2の画面を繰り返し遷移します。

Activity_1.kt
Activity_1.kt
class Activity_1 : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_1)
        val button = findViewById<Button>(R.id.button)
        button.setOnClickListener{
            val intent = Intent(this, Activity_2::class.java)
            startActivity(intent)
        }
    }
}
Activity_2.xml
Activity_2.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#88D9FF"
    tools:context=".Activity_1">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Next"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
Activity_2.kt
Activity_2.kt
class Activity_2 : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_2)
        val button = findViewById<Button>(R.id.button)
        button.setOnClickListener{
            val intent = Intent(this, Activity_1::class.java)
            startActivity(intent)
        }
    }
}
Activity_2.xml
Activity_2.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FF8888"
    tools:context=".Activity_1">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Next"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

トランジションアニメーションの設定は下記のように行います。
まず、layoutファイルのあるディレクトリ「res」直下にディレクトリ「anim」を作ります。
そこに、例えば下記のようにxmlファイルを記述します。
これが、トランジションアニメーションの動きを表します。

slide_in_left.xml
slide_in_left.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="-100%p"
        android:toXDelta="0"
        android:duration="@android:integer/config_mediumAnimTime"/>
</set>
slide_in_right.xml
slide_in_right.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate 
        android:fromXDelta="100%p" 
        android:toXDelta="0"
        android:duration="@android:integer/config_mediumAnimTime"/>
</set>
slide_out_left.xml
slide_out_left.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate 
        android:fromXDelta="0" 
        android:toXDelta="-100%p"
        android:duration="@android:integer/config_mediumAnimTime"/>
</set>
slide_out_right.xml
slide_out_right.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="0"
        android:toXDelta="100%p"
        android:duration="@android:integer/config_mediumAnimTime"/>
</set>

上記のxmlには、こちらに説明がある項目を記述できます。

またディレクトリ「res/values」直下にあるthemes.xml(もしくはstyles.xml)に、上記のxmlファイルで記述したトランジションアニメーションを適用するため下記のように記述します。

themes.xml
themes.xml
<resources>
    <style name="Theme.TestTransitionAnimation" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="android:windowAnimationStyle">@style/AppTheme.Animation.Activity</item>
    </style>
    <style name="AppTheme.Animation.Activity" parent="android:Animation.Activity">
        <item name="android:activityOpenEnterAnimation">@anim/slide_in_right</item>
        <item name="android:activityOpenExitAnimation">@anim/slide_out_left</item>
        <item name="android:activityCloseExitAnimation">@anim/slide_out_right</item>
        <item name="android:activityCloseEnterAnimation">@anim/slide_in_left</item>
    </style>
</resources>

themes.xmlでは、トランジションアニメーションをそれぞれ下記の項目に適用していく。
(参考:Android Develper

  • activityOpenEnterAnimation
    • 新しいactivityを開始するとき、(画面に入ってくる)次のアクティビティで実行されるアニメーション
  • activityOpenExitAnimation
    • 新しいアクティビティを開くときに、(画面を終了している)前のアクティビティに対して実行されるアニメーション
  • activityCloseEnterAnimation
    • 現在のアクティビティを閉じるとき、(画面に入ってくる)次のアクティビティで実行されるアニメーション
  • activityCloseExitAnimation
    • 現在のアクティビティを閉じるときに、(画面を終了している)現在のアクティビティに実行されるアニメーション

ハマってしまったポイント

実際に試していた際、ハマってしまったポイントがあります。
どちらあればよいはずの、styles.xmlとtheme.xmlが両方ディレクトリに存在していた場合、指定したトランジションアニメーションが動作しませんでした。
調べてみると、Android Studio 4.1からはstyles.xmlのかわりにtheme.xmlを使うようです。
https://android-developers.googleblog.com/2020/10/android-studio-41.html
そのため、styles.xmlとtheme.xmlの両方存在する必要はなかったということですね。
なので、styles.xmlに記述していた内容をtheme.xmlに移したところ解決しました。

おわりに

themes.xmlに記述すれば、プロジェクト全体でトランジションアニメーションを適用できるので便利ですね。

Discussion