3
1
お題は不問!Qiita Engineer Festa 2024で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

Android 15 に備えてテキスト入力がある画面を edge-to-edge 対応する

Last updated at Posted at 2024-07-13

Android 15からedge-to-edgeが強制されるようになります。

現在、Android Studioで新規プロジェクトを作成するとedge to edge対応のサンプルが作られるように、ひとまず従来と同等の表示をさせるの難しくありません。
しかし、以下のように、テキスト入力がある画面で、画面下部に送信などのボタンがある画面において、ソフトウェアキーボードが表示されたときは、それに合わせてボタン部分もせり上がらないと一度キーボードを非表示にしないとボタンが押せないという状態になってしまいます。

従来であれば、AndroidManifest.xmlでandroid:windowSoftInputMode="adjustResize"を指定するだけで対応できました。

AndroidManifest.xml
<activity
    android:name=".MainActivity"
    android:windowSoftInputMode="adjustResize"
    android:exported="true"
    >

標準的なedge to edge対応のActivityの場合

MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    enableEdgeToEdge()
    val binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)
    ViewCompat.setOnApplyWindowInsetsListener(binding.main) { v, insets ->
        val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
        v.setPadding(
            systemBars.left,
            systemBars.top,
            systemBars.right,
            systemBars.bottom,
        )
        insets
    }
}

android:windowSoftInputMode="adjustResize"を設定していても以下のように、キーボードに隠れてしまいます。

OnApplyWindowInsetsListenerにてimeのinsetsを含める

ほとんどの場合はこちらの対応で十分かと思います、テンプレート通りだと、OnApplyWindowInsetsListenerにて、systemBarsのinsetsをpaddingに設定していますが、ここでimeのinsetsも含めて設定するようにします。
imeのinsetsはsystemBarsのinsetsを除外したものではないので、maxOfで大きな方の値を設定するようにします。
本来であれば上下左右の設定をすべきかもしれませんが、bottomだけ変更しています。

MainActivity.kt
ViewCompat.setOnApplyWindowInsetsListener(binding.main) { v, insets ->
    val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
    val ime = insets.getInsets(WindowInsetsCompat.Type.ime())
    v.setPadding(
        systemBars.left,
        systemBars.top,
        systemBars.right,
        maxOf(systemBars.bottom, ime.bottom),
    )
    insets
}

WindowInsetsAnimationCallbackを利用する

もう一つの方法、API 30からWindowInsetsAnimationCallbackが使えるようになっており、これを使うことで、IMEが表示されるアニメーションに合わせて処理ができるようになっています。ViewCompatを使うことで過去のバージョンでも利用できます。
以下のように、追加のpaddingを設定することで、ソフトキーボードの上にボタンがくるようにレイアウトを変更することができます。

MainActivity.kt
ViewCompat.setWindowInsetsAnimationCallback(
    binding.main,
    object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_STOP) {
        override fun onProgress(
            insets: WindowInsetsCompat,
            runningAnimations: MutableList<WindowInsetsAnimationCompat>,
        ): WindowInsetsCompat {
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            val ime = insets.getInsets(WindowInsetsCompat.Type.ime())
            binding.buttonArea.updatePadding(
                bottom = (ime.bottom - systemBars.bottom).coerceAtLeast(0)
            )
            return insets
        }
    })

以上です

3
1
2

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
1