MotionLayoutで元のVisibilityを保持したままアニメーションを実行する

# はじめに
MotionLayoutは手軽にアニメーションを管理出来てとても便利なんですが、デフォルトの動作だと元のvisibilityを無視してアニメーションを実行するとViewが表示されてしまいます。こんな感じ↓
ですが、利用する際はINVISIBLEやGONEの場合はその非表示の状態を維持したままアニメーションさせたい場合がほとんどだと思いますので、今回はそのやり方を説明します。
<img width=50% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106116/115efc69-ef42-9dc1-96bb-2cedc67984bb.gif" />

# やり方
### 修正前のコード
まず前述の修正前のアニメーションはこのようなコードで実装されています。

```gradle:app/build.gradle
    // NOTE: MotionLayoutを利用するにはconstraintlayout:2.0.0以上を利用します
    implementation 'androidx.constraintlayout:constraintlayout:2.0.0'
```

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // NOTE: アニメーションを開始
        hello1.setOnClickListener {
            if (motion.currentState == R.id.start) {
                motion.transitionToEnd()
            }else {
                motion.transitionToStart()
            }
        }

        // NOTE: 非表示にする
        hello2.setOnClickListener {
            it.visibility = View.INVISIBLE
        }
    }
}
```

```xml:activity_main.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"
    tools:context=".MainActivity">

    <androidx.constraintlayout.motion.widget.MotionLayout
        android:id="@+id/motion"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layoutDescription="@xml/hello_motion_scene">
        <TextView
            android:id="@+id/hello1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World! 1"
            />
        <TextView
            android:id="@+id/hello2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World! 2"
            />
    </androidx.constraintlayout.motion.widget.MotionLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
```

```xml:xml/hello_motion_scene.xml
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/hello1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toStartOf="@id/hello2"
            />
        <Constraint
            android:id="@+id/hello2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toEndOf="@id/hello1"
            app:layout_constraintEnd_toEndOf="parent"
            />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/hello1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/hello2"
            app:layout_constraintStart_toStartOf="parent"
            android:layout_marginBottom="50dp"
            />
        <Constraint
            android:id="@+id/hello2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toEndOf="@id/hello1"
            app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginBottom="50dp"
            />
    </ConstraintSet>

    <Transition
        app:constraintSetEnd="@id/end"
        app:constraintSetStart="@+id/start"
        app:duration="600"
        />
</MotionScene>
```

### 修正後のコード
visibilityを保持したコードにする場合は `app:visibilityMode="ignore"` を追加してあげるだけ。

```xml:xml/hello_motion_scene.xml
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/hello1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toStartOf="@id/hello2"
            app:visibilityMode="ignore"
            />
        <Constraint
            android:id="@+id/hello2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toEndOf="@id/hello1"
            app:layout_constraintEnd_toEndOf="parent"
            app:visibilityMode="ignore"
            />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/hello1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/hello2"
            app:layout_constraintStart_toStartOf="parent"
            android:layout_marginBottom="50dp"
            app:visibilityMode="ignore"
            />
        <Constraint
            android:id="@+id/hello2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toEndOf="@id/hello1"
            app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginBottom="50dp"
            app:visibilityMode="ignore"
            />
    </ConstraintSet>

    <Transition
        app:constraintSetEnd="@id/end"
        app:constraintSetStart="@+id/start"
        app:duration="600"
        />
</MotionScene>
```

<img width=50% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106116/18034c8b-ba73-b928-6991-306ec54b526e.gif" />

これでアニメーション実行後に勝手に表示されることなく、visibilityを制御できるようになりました！