【Flutter】モーダルダイアログ表示

Flutter

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'),
            ),
          ],
        ),
      ),
    );
  }
}

コメント

タイトルとURLをコピーしました