Flutterでのダイアログ利用
こんにちは、株式会社Pentagonでエンジニアをしている阿久津です。
今回はFlutterでダイアログの利用方法について取り上げます。
ダイアログとは
ISOによると、"ユーザとシステムが相互作用するもの"みたいな定義らしい。
interaction between a user and an interactive system as a sequence of user actions (inputs) and system responses (outputs) in order to achieve a goal
例(GitHubをよくわからず操作している時、押したらダメ、絶対)
ポップアップ、モーダルとか色々と言い方(一般的な意味も若干違う)があるものの、今回の記事では以下をダイアログと呼びます。
モーダル = "画面の上になんか出てくるやつ"
Flutterで使えるダイアログ
以下のような"中央に浮き上がってくるタイプ"、"下部からせり上がってくるタイプ"の2種類が簡単に利用できます。
ダイアログの実装方法
中央に浮き上がってくるタイプ(showDialog)
void _showDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return const AlertDialog(
content: Text('真ん中に出てくるやつ'), // <= ここでダイアログに表示したいWidgetを返してあげればOK
);
},
);
}
下部からせり上がってくるタイプ(showModalBottomSheet)
void _showModalBottomSheet(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (context) {
return const SizedBox( // <= ここでダイアログに表示したいWidgetを返してあげればOK
height: 150,
child: Text(
'下から出て来るやつ',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16),
),
);
},
);
}
簡単。以上です。
注意点(ハマるかもポイント)
問題1:ダイアログの内部でListViewやColumnを利用すると縦幅が伸びてしまう。
void _showDialogWithColumn(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Column( // <= ここでダイアログに表示したいWidgetを返してあげればOK
children: const [
Text('真ん中に出てくるやつ'),
Text('真ん中に出てくるやつ'),
Text('真ん中に出てくるやつ'),
],
),
);
},
);
}
解決法1: `mainAxisSize: MainAxisSize.min,`を設定
void _showDialogWithColumn(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min, <= ここ
children: const [
Text('真ん中に出てくるやつ'),
Text('真ん中に出てくるやつ'),
Text('真ん中に出てくるやつ'),
],
),
);
},
);
}
問題2:ListViewを使うとレンダリングで怒られる
void _showDialogWithList(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: ListView(
children: const [
Text('真ん中に出てくるやつ'),
Text('真ん中に出てくるやつ'),
Text('真ん中に出てくるやつ'),
],
),
);
},
);
}
======== Exception caught by rendering library =====================================================
The following assertion was thrown during paint():
RenderBox was not laid out: RenderPhysicalShape#94df0 relayoutBoundary=up2
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1930 pos 12: 'hasSize'
解決法2:SizedBoxでListViewのサイズを指定する
void _showDialogWithList(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: SizedBox( <= ここ
height: 80,
width: 100,
child: ListView(
children: const [
Text('真ん中に出てくるやつ'),
Text('真ん中に出てくるやつ'),
Text('真ん中に出てくるやつ'),
],
),
),
);
},
);
}
どちらもFlutterのBoxConstraints周りについて理解している(覚えていると)と遭遇しないであろう問題なので、そのうちBoxConstraintsについても記事を書こうと思います。
参考サイト
ISO(Online Browsing Platform):
https://www.iso.org/obp/ui/#iso:std:iso:9241:-143:ed-1:en