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をよくわからず操作している時、押したらダメ、絶対)
https://assets.st-note.com/production/uploads/images/60025988/picture_pc_9157aaa4cf845901c9ee509f5d32b460.png

ポップアップ、モーダルとか色々と言い方(一般的な意味も若干違う)があるものの、今回の記事では以下をダイアログと呼びます。
モーダル = "画面の上になんか出てくるやつ"

Flutterで使えるダイアログ

以下のような"中央に浮き上がってくるタイプ"、"下部からせり上がってくるタイプ"の2種類が簡単に利用できます。

https://assets.st-note.com/production/uploads/images/60026732/picture_pc_63959f07833244798eaf5280e88eb7e2.png?width=800

ダイアログの実装方法

中央に浮き上がってくるタイプ(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('真ん中に出てくるやつ'),
           ],
         ),
       );
     },
   );
 }

https://assets.st-note.com/production/uploads/images/60027222/picture_pc_ef3e1a4900254e04cfb5827cac1b6b31.png?width=800

解決法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('真ん中に出てくるやつ'),
           ],
         ),
       );
     },
   );
 }

https://assets.st-note.com/production/uploads/images/60027272/picture_pc_8bf66582a57dbfc5772af7c6096e427d.png?width=800

問題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('真ん中に出てくるやつ'),
             ],
           ),
         ),
       );
     },
   );
 }

https://assets.st-note.com/production/uploads/images/60027480/picture_pc_bb86719611527f5da9c541a70425d4d0.png?width=800

どちらもFlutterのBoxConstraints周りについて理解している(覚えていると)と遭遇しないであろう問題なので、そのうちBoxConstraintsについても記事を書こうと思います。

参考サイト

ISO(Online Browsing Platform):
   https://www.iso.org/obp/ui/#iso:std:iso:9241:-143:ed-1:en

採用情報はこちら
目次