【Android】Android 11から始めるIME Transitions

## IME Transitionsとは
Android 11 DP2から追加されたWindowInsets APIの一つです。
https://android-developers.googleblog.com/2020/03/android-11-developer-preview-2.html

<img width="260px" alt="ime_transition.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223159/4642a693-6f20-aac1-9129-c20d98249d18.gif">


### さっくり作ってみた

```kotlin:MainActivity.kt
import android.graphics.Insets
import android.os.Bundle
import android.view.*
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.updateLayoutParams
import androidx.core.view.updateMargins
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity() {

    private val spacing36 by lazy {
        applicationContext.resources.getDimensionPixelOffset(R.dimen.spacing_36)
    }

    private val spacing16 by lazy {
        applicationContext.resources.getDimensionPixelOffset(R.dimen.spacing_16)
    }

    private val listener = object: WindowInsetsAnimationControlListener {
        override fun onCancelled() {
            animationController = null
            isFirst = true
        }

        override fun onReady(controller: WindowInsetsAnimationController, types: Int) {
            animationController = controller
        }
    }

    private var animationController: WindowInsetsAnimationController? = null

    private var isFirst = true

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        window.setDecorFitsSystemWindows(false)
        
        val callback = object: WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
            override fun onProgress(
                insets: WindowInsets,
                animations: MutableList<WindowInsetsAnimation>
            ): WindowInsets {
                text_input_layout.updateLayoutParams<ViewGroup.MarginLayoutParams> {
                    updateMargins(bottom = insets.getInsets(WindowInsets.Type.ime()).bottom + spacing16)
                }
                return insets
            }
        }
        text_input_layout.setWindowInsetsAnimationCallback(callback)

        scroll_view.setOnScrollChangeListener { view, x, y, oldX, oldY ->
            if (isFirst && y != 0) {
                isFirst = false
                text_input_layout.windowInsetsController?.controlWindowInsetsAnimation(
                    WindowInsets.Type.ime(),
                    -1,
                    null,
                    listener
                )
            }
            animationController?.setInsetsAndAlpha(Insets.of(0, 0, 0, scroll_view.scrollY - spacing36), 1f, 0f)
        }
    }
}
```

レイアウトファイルはScrollViewのなかにTextInputLayoutを追加すれば動く。

## 所感
その他にも、`inputLayout.windowInsetsController.hide() or show()`でキーボードの表示切り替えができます。
また、サンプルコードではTextInputLayoutにFocusが当たってるときと当たっていない時の制御を入れてないので、そこらへんの実装をちゃんとすればより良いUIになりそうです。

※DP2のため今後変更の可能性があります。

### 参考
https://android-developers.googleblog.com/2020/03/android-11-developer-preview-2.html
https://developer.android.com/reference/kotlin/android/view/WindowInsetsAnimation.Callback
https://developer.android.com/reference/android/view/WindowInsetsAnimationController