Android11で新たに導入されたAPIの中にキーボードの表示/非表示を検知するAPIが追加されたという情報を目にし、試してみました。
調べていく中でいろいろと仕組みをしっかり理解したほうがよさそうな雰囲気を感じたのですが今回はHowに焦点を絞ってまとめます。
実装
実装はいたって簡単です。
1.まず WindowsInset
のコールバックを有効にするための設定を行います
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requireActivity().window.setDecorFitsSystemWindows(false)
}
setDecorFitsSystemWindowsのAPIドキュメント
2.続いて WindowInset
のアニメーションのコールバックをViewに設定します
どのViewに設定しても良いようなのでここではrootのviewに設定します
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.setWindowInsetsAnimationCallback(object: WindowInsetsAnimation.Callback(DISPATCH_MODE_CONTINUE_ON_SUBTREE) {
override fun onProgress(
insets: WindowInsets,
runningAnimations: MutableList<WindowInsetsAnimation>
): WindowInsets {
return insets
}
})
}
WindowInsetsAnimation.CallbackのAPIドキュメント
上記は必要最低限の実装になりますがキーボードの表示を検知するには onProgress
は向いていません。代わりに
3. onEnd
をオーバーライドしてキーボードの表示/非表示アニメーション終了を検知します
override fun onEnd(animation: WindowInsetsAnimation) {
super.onEnd(animation)
if (animation.typeMask == WindowInsets.Type.ime()) {
val keyboardVisibility =
view.rootWindowInsets.isVisible(WindowInsets.Type.ime())
val message = if (keyboardVisibility) "キーボード表示" else "キーボード非表示"
Toast.makeText(context, message, LENGTH_SHORT).show()
}
}
コード解説
上記実装の中の3つめの onEnd
に関しては前提知識がないとなぜこんなコードになっているかわかりにくいと思うのでちょっとだけ解説します。
今回利用した WindowInsetsAnimation.Callback
はおそらくキーボードの動き以外も検知するものだと思われます(ここはしっかり調査したわけではないのですがWindowInsets.Type
がime以外にもいろいろあったためそう推測しました)
なのでanimation.typeMask==WindowInsets.Type.ime()
を行いアニメーションの対象がキーボードかどうかを判定してからキーボードの表示状態をチェックしているという形になっています。
所感
Android11以上でしか利用できないのでまだまだこの機能に頼ることはできませんが、今までの「Viewの変化を自分で検知してキーボード表示/非表示の判定をする」に比べると格段にわかりやすくなったと思います。
ただWindowInsetsについてはもっと理解をしなければとも感じたのでこれからも学習を続けたいと思います。
参考・関連記事
- https://developer.android.com/about/versions/11/features?hl=ja
- https://developer.android.com/reference/android/view/View?hl=ja#setWindowInsetsAnimationCallback(android.view.WindowInsetsAnimation.Callback)
- https://developer.android.com/reference/android/view/Window#setDecorFitsSystemWindows(boolean)
- https://qiita.com/takahirom/items/c0864ad6ec2a6c013552
- https://qiita.com/HaSuzuki/items/f39e0857eaa7dcd88637
- https://github.com/android/user-interface-samples/tree/master/WindowInsetsAnimation