IME Transitionsとは
Android 11 DP2から追加されたWindowInsets APIの一つです。
https://android-developers.googleblog.com/2020/03/android-11-developer-preview-2.html
さっくり作ってみた
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