🐽
Flutterでキーボード表示した時に画面スクロールできるように
Before
↓のようなformの画面で、キーボード表示した時に、レイアウト崩れることがあります。
例えばコードはこういう感じ:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(20),
child: Column(children: [
Container(
height: 300,
color: Colors.grey,
),
Expanded(
child: Form(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
decoration: const InputDecoration(hintText: 'Username'),
),
TextFormField(
decoration: const InputDecoration(hintText: 'Password'),
),
],
)),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.blue,
minimumSize: const Size.fromHeight(44), // NEW
),
child: const Text('Log in'),
onPressed: () {},
),
const SizedBox(
height: 34,
)
]),
),
);
}
Goal
- レイアウト崩れない
- キーボード表示時画面全体スクロールできるように(よくあるUI)
After
How
画面の要素を全部SizedBoxに入れ、SingleChildScrollViewでラップします。
SizedBoxのheightはcontextの高さからapp barの高さを引いて設定します。
Scaffold.of(context)そのまま使うと、contextはScaffoldをinitしたcontextになり、Scaffoldのchildのcontextではないため、exceptionが出ます。
そのため、Builderでラップします。
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Builder(
builder: ((context) => SingleChildScrollView(
child: SizedBox(
height: MediaQuery.of(context).size.height -
(Scaffold.of(context).appBarMaxHeight ?? 0),
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(children: [
Container(
height: 300,
color: Colors.grey,
),
Expanded(
child: Form(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
decoration:
const InputDecoration(hintText: 'Username'),
),
TextFormField(
decoration:
const InputDecoration(hintText: 'Password'),
),
],
)),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.blue,
minimumSize: const Size.fromHeight(44), // NEW
),
child: const Text('Log in'),
onPressed: () {},
),
const SizedBox(
height: 34,
)
]),
),
),
))));
}
Discussion