調整前の状態確認
まずは、文字入力エリアをタップすると、その下に配置している『OK』ボタンがキーボードによって隠されてしまう例を確認しておきましょう。
誤タップを防ぐために入力エリアとボタンの距離を離したいケースは多いかと思いますが、だからと言って次のようにボタンを画面の下部あたりに配置すると、ボタンがキーボード表示によって隠されてしまいます。
@Composable
fun InputView() {
Box(
modifier = Modifier
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
TextField(value = "", onValueChange = { TODO() })
Button(
onClick = { /*TODO*/ },
modifier = Modifier
.align(Alignment.BottomCenter)
.offset(y = (-72).dp)
.width(250.dp)
) {
Text(text = "OK")
}
}
}
『キーボード表示エリアと重ならない位置にボタンを配置する』…といったアプローチも解決策の一つではありますが、今回はボタンの配置を変更せずにこの問題を解決してみようと思います。
次のステップでは、キーボード表示時にボタンがキーボードで隠されない位置まで自動で移動するように設定を変更してみましょう。
POINT!
- ・画面下部にボタンを配置してしまうと、キーボードの表示によってボタンが隠されてしまう場合がある!
- ・そもそも、ボタンを画面下部に配置しないというのも一つの解決策ではある!
- ・配置を変えずに、ボタンが隠されないようにする方法もある(次のステップで紹介)!
1: AndroidManifest.xmlの編集
キーボードの出現によってボタンなどのパーツが隠されないようにするには、AndroidManifest.xmlファイルのactivity
要素に、android:windowSoftInputMode="adjustResize"
を追加します。
<!-- AndroidManifest.xml file: -->
<activity
android:name="..."
android:label="..."
android:exported="true"
android:windowSoftInputMode="adjustResize"
android:theme="...">
adjustResize
オプションを設定することにより、ソフトウェアキーボードの表示によって隠れてしまう可能性のあるコンテンツを自動的にリサイズし、スクリーン上で見えるように調整されます。
なので、この設定だけでもキーボード表示でボタンが隠されてしまう問題を解決できます。
しかしこの設定だけでは、瞬間的にコンテンツが移動する(=アニメーションにならない)ので、やや違和感のある挙動になってしまいます。
下の動画は、サンプルアプリに adjustResize
の設定を加えただけの状態で、入力エリアをタップしてキーボードを表示させた様子を録画したものですが、コンテンツが瞬間的に移動していることが確認できます。
ボタンがキーボードで隠されなくなったのは良いのですが、コンテンツの移動をアニメーション化して、より自然に感じられるようにしたいですね。次のステップではそのための調整を加えていきましょう。
POINT!
- ・キーボードの表示でコンテンツが隠れないようにするには、activity要素に
adjustResize
を設定する!
- ・ただし、これだけではコンテンツの移動が瞬間的になってしまう(アニメーションにならない)!
- ・コンテンツの移動をアニメーション化するには、もうひと手間必要!
2: MainActivityクラスの編集
まず、アプリケーションのレイアウトをデバイスのエッジ(端)まで拡張して表示する設定を有効にするために、Activity.onCreate
の中で enableEdgeToEdge()
を呼び出します。
この設定により、ステータスバーやナビゲーションバーの背後にコンテンツが表示されるようになり、画面全体を有効に活用することができます。
キーボードの表示・非表示の切り替え時に、コンテンツの移動を滑らか(アニメーション)にするためには欠かせない設定になります。
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
…
}
次に、アプリケーションにインセットを適用するため、アプリのコンテンツ(ビュー)をSurfaceやBoxなどでラップし、Modifire.safeDrawingPadding()
を指定します。
setContent {
KeyboardAvoidingTheme {
Surface(
modifier = Modifier
.fillMaxSize()
.safeDrawingPadding(),
color = MaterialTheme.colorScheme.background
) {
InputView()
}
}
}
これらの設定により、キーボードによってボタンが隠されないだけでなく、キーボードの出現に合わせてアニメーションと共に移動するようになります。(下の動画を参照)
このようにキーボード表示に伴うコンテンツの移動をアニメーション化することで、アプリケーションの挙動がより自然になり、ユーザー体験の向上が期待できます。
おわりに
私たちが「アプリ開発を学ぶ」と言うとき、どちらかと言えばデザインよりも、ソースコード(ロジック)の解読・理解の方に意識が向かいがちかと思います。
もちろん、プログラムのロジック面をより深く学ぶことは大切ですし、それを否定するつもりは全くありません。
ですが、UI/UXを含めたデザインもまた、アプリ開発における重要な要素です。
今回の記事では、『キーボードの表示によってボタンが隠されないようにする』という、UI/UXデザインと関係が深いテーマを扱いましたが、他にもデザインに関する知識が必要となるケースは色々考えられます。
- ボタンはタップしやすい大きさか?
- タップしやすい位置に配置されているか?
- OKボタンやキャンセルボタンには、それぞれ適切なカラーが指定されているか?
…などなど、アプリ開発者として知っておきたいデザインに関する知識は多岐にわたります。
筆者としては、難しいコードを理解して書けるようになるということだけを目標とするのではなく(それも良いのですが)、アプリ開発に欠かせない知識を全体的にバランスよく身につけていくことが、個人アプリ開発者にとっては大切なのではないかと思っています。
POINT!
- ・コンテンツの移動をアニメーション化するには、MainActivityクラスの編集が必要!
- ・
enableEdgeToEdge()
は、コンテンツを画面の端まで表示できるようにするもの!
- ・
safeDrawingPadding()
はコンテンツが安全に描画されるように適切なパディングを設定する!