3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ZOZOテクノロジーズ #3Advent Calendar 2020

Day 12

Android11でキーボードの表示/非表示を検知する

Last updated at Posted at 2020-12-11

Android11で新たに導入されたAPIの中にキーボードの表示/非表示を検知するAPIが追加されたという情報を目にし、試してみました。

調べていく中でいろいろと仕組みをしっかり理解したほうがよさそうな雰囲気を感じたのですが今回はHowに焦点を絞ってまとめます。

実装

実装はいたって簡単です。

1.まず WindowsInset のコールバックを有効にするための設定を行います

Fragment

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        requireActivity().window.setDecorFitsSystemWindows(false)
    }

setDecorFitsSystemWindowsのAPIドキュメント

2.続いて WindowInset のアニメーションのコールバックをViewに設定します

どのViewに設定しても良いようなのでここではrootのviewに設定します

Fragment

    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 をオーバーライドしてキーボードの表示/非表示アニメーション終了を検知します

WindowInsetsAnimation.Callback
    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についてはもっと理解をしなければとも感じたのでこれからも学習を続けたいと思います。

参考・関連記事

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?