Flutterでウイジェットをモーダルダイアログ表示させる方法について解説します。
※ちなみに「その画面を閉じるまで他の操作ができない」画面表示のことをモーダル表示といいます。
モーダル表示(showDialog)
Flutterでのモーダル表示は、showDialog()で簡単に行えます。
// 戻り値と、戻り時の処理が不要であれば、result、awaitは不要です
var result = await showDialog(
context: context,
barrierDismissible: false,
builder: (_) {
return 任意のウィジェット;
}
);
// awaitで待機した場合はここで戻り後の処理を書きます
- barrierDismissible:
画面外をタップした時に画面を閉じるかどうか(デフォルトはtrue)
表示したい任意のウィジェットをbuilderで返せばモーダルで表示してくれます。
ダイアログを閉じる
ダイアログを閉じる場合は、Navigator.pop(context)を呼びます。
Navigator.pop(context);
// 戻り値を返したい場合は二番目の引数にデータを渡します
Navigator.pop(context,_data);
既存のダイアログ
Flutter標準で、よくあるダイアログが既に用意されているので、ウィジェットを自作しなくてもこれらを利用できます。
SimpleDialog
複数の選択項目から選ばせる用途向きのダイアログです。

SimpleDialog(
title: const Text('タイトル'),
children: <Widget>[
SimpleDialogOption(
child: const Text('Item 1'),
onPressed: () => Navigator.pop(context),
),
SimpleDialogOption(
child: const Text('Item 2'),
onPressed: () => Navigator.pop(context),
),
],
);
- title: タイトルに表示するウィジェット
- children: 選択項目を列挙(SimpleDialogOptionを利用します)
選択項目はonPressedとchildがセットになっているSimpleDialogOptionが用意されているので、これを利用します。(違うウィジェットでも問題はありません)
AlertDialog
表示するメッセージに対して何らかのアクションを促すアラート画面用途のダイアログです。こちらはOK/Cancelなどのアクションを定義します。

AlertDialog(
title: const Text('タイトル'),
content: const Text('アラートの本文'),
actions: [
ElevatedButton(
child: const Text('OK'),
onPressed: () => Navigator.pop(context),
),
],
);
- title: タイトルに表示するウィジェット
- content: 表示するコンテンツのウィジェット
- actions: アクション用のウィジェット(基本はボタン類)
サンプルコード
showDialogで、閉じるボタン、SimpleDialog、AlertDialog、の3種類のダイアログを表示し、戻り値をテキストで表示するサンプルコードです。

import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'showDialog'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _resultString = 'result';
void _setResultString(Object? result) =>
_resultString = (result ?? 'null') as String;
void _showDialog() async {
var result = await showDialog(
context: context,
builder: (_) {
return FittedBox(
fit: BoxFit.none,
child: ElevatedButton(
child: const Text('close'),
onPressed: () => Navigator.pop(context, 'close'),
),
);
},
);
setState(() => _setResultString(result));
}
void _showSimpleDialog() async {
var result = await showDialog(
context: context,
builder: (_) {
return SimpleDialog(
title: const Text('タイトル'),
children: <Widget>[
SimpleDialogOption(
child: const Text('Item 1'),
onPressed: () => Navigator.pop(context, 'Item 1'),
),
SimpleDialogOption(
child: const Text('Item 2'),
onPressed: () => Navigator.pop(context, 'Item 2'),
),
],
);
},
);
setState(() => _setResultString(result));
}
void _showAlertDialog() async {
var result = await showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: const Text('タイトル'),
content: const Text('アラートの本文'),
actions: [
ElevatedButton(
child: const Text('OK'),
onPressed: () => Navigator.pop(context, 'OK'),
),
],
);
},
);
setState(() => _setResultString(result));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(_resultString),
const SizedBox(height: 10),
ElevatedButton(
onPressed: _showDialog,
child: const Text('showDialog'),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: _showSimpleDialog,
child: const Text('SimpleDialog'),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: _showAlertDialog,
child: const Text('AlertDialog'),
),
],
),
),
);
}
}
コメント