[Flutter] ダイアログの種類と使い分け方をカチッとまとめる

Flutterのダイアログについてまとめます。

結論としては、こんな感じです。
・選択肢ダイアログ ： SimpleDialog
・ボタンつきまたはカスタマイズ ： AlertDialog
・それでも実現できない場合 ： 新規ページにダイアログを実装する

## Material編
### SimpleDialog
![SimpleDialog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396229/fe564371-8276-04e4-19f2-3ca09cf903a9.png)

SimpleDialogは、基本的に選択肢から選ぶようなダイアログの場合に使用します。
選択肢はSimpleDialogOptionを使って実装できます。

また、Dialogを表示する際にはshowDialog()メソッドを呼び出します。
これはDialogの種類に関わらず共通事項です。

```dart
showDialog(
  context: context,
  builder: (context) {
    return SimpleDialog(
      title: Text("タイトル"),
      children: <Widget>[
        // コンテンツ領域
        SimpleDialogOption(
          onPressed: () => Navigator.pop(context),
          child: Text("１項目目"),
        ),
          :
          :
      ],
    );
  },
);
```
[→全文を見る](https://gist.github.com/coka01/f9dfda4f244ff7e90544dda8cb8afb8d)

念のため、以下の[公式のSimpleDialogの文章](https://api.flutter.dev/flutter/material/SimpleDialog-class.html)です。

>A simple dialog offers the user a choice between several options.

（和訳）
"SimpleDialogで、ユーザーはいくつかのオプションから選択できます。"


### AlertDialog

![AlertDialog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396229/164a4a3d-5da3-6d73-7a7f-7d583aa78d2c.png)

タイトル、メッセージ、ボタンがある一般的なダイアログです。

```dart
showDialog(
  context: context,
  builder: (_) {
    return AlertDialog(
      title: Text("タイトル"),
      content: Text("メッセージメッセージメッセージメッセージメッセージメッセージ"),
      actions: <Widget>[
        // ボタン領域
        FlatButton(
          child: Text("Cancel"),
          onPressed: () => Navigator.pop(context),
        ),
        FlatButton(
          child: Text("OK"),
          onPressed: () => Navigator.pop(context),
        ),
      ],
    );
  },
);
```
[→全文を見る](https://gist.github.com/coka01/2a3179f0951c8f45852568ae8c73c137#file-alertdialog)

また、ある程度カスタマイズしたダイアログも実装できます。
その際には、[SingleChildScrollViewなどを使用することが推奨](https://api.flutter.dev/flutter/material/AlertDialog-class.html)されています。

その中で、ColumnやRowなどを使って複数Widgetを配置することで様々なダイアログを実装できます。

<img width="341" alt="alert.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396229/e793acc5-424b-b384-3116-f79263870d3c.png">

```dart
showDialog(
  context: context,
  builder: (context) {
    Column(
      children: <Widget>[
        AlertDialog(
          title: Text("タイトル"),
          content: SingleChildScrollView(
            child: ListBody(
              children: <Widget>[
                Column(
                  // コンテンツ
                ),
              ],
            ),
          ),
          actions: <Widget>[
            // ボタン
          ],
        ),
      ],
    );
  }
);
```
[→全文を見る](https://gist.github.com/coka01/dcf32f3a1c50d5216cc24df382074420)

### 新規画面上にダイアログを実装する

![CustomDialog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396229/ed7f8d71-41f5-8081-ea36-ed5ceef53c2d.png)

画像がはみ出したりするなど、AlertDialogやSimpleDialogで実現できなかった場合はこの方法になると思います。

ModalRouteを継承したページを実装します。
一枚の画面となりますのでpush()やpushNamed()で表示します。

```dart
import 'package:flutter/material.dart';

class OverlayDialogPage extends ModalRoute<void> {
  @override
  Duration get transitionDuration => Duration(milliseconds: 100);

  @override
  bool get opaque => false;
  :
  :
```

少しコードが長いので、実装したい方は[こちら](https://gist.github.com/coka01/4753b91733dfdaa495c92ef2f151084e)をご確認ください。

## 補足情報
### Dialog
[Dialog Widget](https://api.flutter.dev/flutter/material/Dialog-class.html)も用意されていますが、執筆現在では以下の表記があり、直接使用するのは避けたほうがよさそうです。

>Rather than using this widget directly, consider using AlertDialog or SimpleDialog, which implement specific kinds of material design dialogs.



（和訳）
このウィジェットを直接使用するのではなく、特定の種類のダイアログを実装するAlertDialogまたはSimpleDialogの使用を検討してください。

### AboutDialog

![AboutDialog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396229/4b39e3dc-cebd-eef7-bd37-82f1f09553dd.png)

アプリ名やアプリバージョンなどを表示して、OSSのライセンスページに遷移できるダイアログです。
このダイアログは、以下のようにshowAboutDialog()で呼び出せます。

（showLisencePage()で開くことができるライセンスページになりますが、ここでは詳細は割愛します。）

```dart
showAboutDialog(
  context: context,
  applicationIcon: Icon(Icons.photo),
  applicationName: "アプリ名",
  applicationVersion: "2.0.1",
  applicationLegalese: "あいうえお",
);
```

## Material編 まとめ
・選択肢ダイアログ ： SimpleDialog
・ボタンつきまたはカスタマイズ ： AlertDialog
・それでも実現できない場合 ： 新規ページにダイアログを実装する


## Cupertino編
### CupertinoAlertDialog

![CupertinoAlertDialog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396229/ca833b28-564e-c988-489f-22e7e2581804.png)

実装方法はAlertDialogと同じで、titleやcontent、actionsなどにWidgetを配置することで、簡単にiOSダイアログが組めます。

```dart
showDialog(
  context: context,
  builder: (context) {
    return CupertinoAlertDialog(
      title: Text("タイトル"),
      content: Text("メッセージ"),
      actions: <Widget>[
        CupertinoDialogAction(
          child: Text("Delete"),
          isDestructiveAction: true,
          onPressed: () => Navigator.pop(context),
        ),
        CupertinoDialogAction(
          child: Text("OK"),
          onPressed: () => Navigator.pop(context),
        ),
      ],
    );
  },
);
```

### CupertinoDialog
[CupertinoDialog](https://api.flutter.dev/flutter/cupertino/CupertinoDialog-class.html)の使用はやめたほうがよさそうです。

>Rather than using this widget directly, consider using CupertinoAlertDialog, which implement a specific kind of dialog."

（和訳）
”このウィジェットを直接使用するのではなく、特定の種類のダイアログを実装するCupertinoAlertDialogを使用することを検討してください。"

（現在Deprecatedになっているようです。）

### Cupertino編まとめ
実質、CupertinoAlertDialogのみ用意されていますので、素直にこれを使いましょう。
カスタマイズしたい場合には、先ほどの[新規画面上にダイアログを実装する](https://qiita.com/drafts/4c1aea5fb1646e463f91#%E6%96%B0%E8%A6%8F%E7%94%BB%E9%9D%A2%E4%B8%8A%E3%81%AB%E3%83%80%E3%82%A4%E3%82%A2%E3%83%AD%E3%82%B0%E3%82%92%E5%AE%9F%E8%A3%85%E3%81%99%E3%82%8B)方法くらいでしょうか。

## その他参考
・[Widget Catalog](https://flutter.dev/docs/development/ui/widgets)
・[stackoverflow how-to-make-a-full-screen-dialog-in-flutter](https://stackoverflow.com/questions/51908187/how-to-make-a-full-screen-dialog-in-flutter)

以上です！！
間違い等ありましたら、ご指摘お願いします。