得益于モバイル端の利点、flutter のダイアログの種類は比較的多く、以下にいくつかの一般的なスタイルのダイアログを示します。
必要な Scaffold コンポーネントのレイアウトは以下の通りです:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("ダイアログ"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _alertDailog,
child: const Text("アラートポップアップ-AlertDialog"),
),
ElevatedButton(
onPressed: _simpleDialog,
child: const Text("選択ポップアップ-SimpleDialog"),
),
ElevatedButton(
onPressed: _modalBottomSheet,
child: const Text("モーダルポップアップ-ModalBottomSheet"),
),
ElevatedButton(
onPressed: _toast,
child: const Text("トーストポップアップ-Toast"),
),
]),
),
);
}
AlertDialog(通知ダイアログ)#
通知ダイアログはこのようになります:
//alertDailog(非同期に注意)
void _alertDailog() async {
var result = await showDialog(
context: context,
barrierDismissible: false, //灰色の背景をクリックしてキャンセルを許可しない
builder: (context) {
return AlertDialog(
title: const Text("私はalertDialogです"),
content: Text("私はDialogの主体です"),
actions: [
TextButton(
onPressed: () {
print("ok");
//ダイアログを閉じる、直接ルートに戻るだけで良い
Navigator.pop(context, true);
},
child: const Text("確定")),
TextButton(
onPressed: () {
print("cancel");
Navigator.pop(context, false);
},
child: const Text("キャンセル")),
],
);
});
print(result);
}
SimpleDialog#
通常のダイアログには任意のコンポーネントを配置できます。ここでは選択機能を実装できます。
void _simpleDialog() async {
var res = await showDialog(
context: context,
builder: (context) {
return SimpleDialog(
title: const Text("言語を選択してください"),
children: [
SimpleDialogOption(
onPressed: () {
Navigator.pop(context, "中国語");
},
child: const Text("中国語"),
),
const Divider(),
SimpleDialogOption(
onPressed: () {
Navigator.pop(context, "英語");
},
child: const Text("英語"),
),
const Divider(),
SimpleDialogOption(
onPressed: () {
Navigator.pop(context, "日本語");
},
child: const Text("日本語"),
)
],
);
});
print(res);
}
showModalBottomSheet(ボトムポップアップモーダル)#
まずは効果を見てみましょう:
ここではショッピングカートの例を使って説明します:
void _modalBottomSheet() async {
var res = await showModalBottomSheet(
context: context,
builder: (context) {
return SizedBox(
height: 250,
child: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
child: Row(
children: [
const Padding(
padding: EdgeInsets.fromLTRB(0, 0, 10, 0),
child: Text(
"色:",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
Padding(
padding: const EdgeInsets.all(10),
child: ElevatedButton(
onPressed: () {
Navigator.pop(context, "赤");
},
style: ButtonStyle(
backgroundColor: const MaterialStatePropertyAll(
Color.fromARGB(255, 254, 80, 42),
),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50)),
),
),
child: const Text("赤"),
),
),
Padding(
padding: const EdgeInsets.all(10),
child: ElevatedButton(
onPressed: () {
Navigator.pop(context, "黄色");
},
style: ButtonStyle(
backgroundColor: const MaterialStatePropertyAll(
Color(0x00000ccc),
),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50)),
),
),
child: const Text("黄色"),
),
),
Padding(
padding: const EdgeInsets.all(10),
child: ElevatedButton(
onPressed: () {
Navigator.pop(context, "青");
},
style: ButtonStyle(
backgroundColor: const MaterialStatePropertyAll(
Color(0x00000ccc),
),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50)),
),
),
child: const Text("青"),
),
),
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
child: Row(
children: [
const Padding(
padding: EdgeInsets.fromLTRB(0, 0, 10, 0),
child: Text(
"サイズ:",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
Padding(
padding: const EdgeInsets.all(10),
child: ElevatedButton(
onPressed: () {
Navigator.pop(context, "XL");
},
style: ButtonStyle(
backgroundColor: const MaterialStatePropertyAll(
Color.fromARGB(255, 254, 80, 42),
),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50)),
),
),
child: const Text("XL"),
),
),
Padding(
padding: const EdgeInsets.all(10),
child: ElevatedButton(
onPressed: () {
Navigator.pop(context, "XML");
},
style: ButtonStyle(
backgroundColor: const MaterialStatePropertyAll(
Color(0x00000ccc),
),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50)),
),
),
child: const Text("XML"),
),
),
Padding(
padding: const EdgeInsets.all(10),
child: ElevatedButton(
onPressed: () {
Navigator.pop(context, "XXL");
},
style: ButtonStyle(
backgroundColor: const MaterialStatePropertyAll(
Color(0x00000ccc),
),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50)),
),
),
child: const Text("XXL"),
),
),
],
),
),
SizedBox(
height: 100,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(10),
child: ElevatedButton(
onPressed: () {
Navigator.pop(context, "ok");
},
style: ButtonStyle(
backgroundColor: const MaterialStatePropertyAll(
Colors.red,
),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
),
),
child: const SizedBox(
width: 150,
height: 40,
child: Center(
child: Text("カートに追加"),
),
),
),
),
Padding(
padding: const EdgeInsets.all(10),
child: ElevatedButton(
onPressed: () {
Navigator.pop(context, "ok購入");
},
style: ButtonStyle(
backgroundColor: const MaterialStatePropertyAll(
Colors.orange,
),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
),
),
child: const SizedBox(
width: 150,
height: 40,
child: Center(
child: Text("今すぐ購入"),
),
),
),
),
],
),
),
],
),
);
});
print(res);
}
Fluttertoast(トーストメッセージ)#
注:flutter にはトーストが標準で付属していないため、リポジトリからインストールする必要があります。
flutter pub add fluttertoast
トーストの使用:
void _toast() {
Fluttertoast.showToast(
msg: "トーストです",
toastLength: Toast.LENGTH_SHORT, //Androidプラットフォームで有効(トースト表示時間)
gravity: ToastGravity.CENTER, //位置
timeInSecForIosWeb: 1, //表示時間 iOSとWeb向け
backgroundColor: Colors.red, //背景色
textColor: Colors.red, //テキスト色
fontSize: 16.0, //テキストフォントサイズ
);
}
効果:
カスタムダイアログ#
Flutter では、showDialog
の builder 関数を使用してカスタム Widget を追加できます。
//カスタムダイアログ
void _myDialog() async {
var res = await showDialog(
context: context,
//灰色の背景をクリックしても消えない
barrierDismissible: false,
builder: (context) {
//カスタムダイアログを使用
return MyDailog(
title: "kano",
content: "kanokano.cn",
onTap: () {
//非同期イベント
Navigator.pop(context, '閉じました');
},
);
});
print(res);
}
MyDialog.dart
import 'package:flutter/material.dart';
class MyDailog extends Dialog {
late String title;
late String content;
late Function()? onTap;
MyDailog(
{Key? key,
required this.title,
required this.content,
required this.onTap})
: super(key: key);
@override
Widget build(BuildContext context) {
//Materialコンポーネントは背景を透明に設定できるので、これを使用します
return Material(
//透明に設定(ついでに外側をクリックしてダイアログを閉じる機能を有効にします)
type: MaterialType.transparency,
//灰色の背景をクリックしても消えない
child: Center(//Centerで包むことで、ダイアログが全画面を覆うことを防ぎます
child: Container(
height: 300,
width: 300,
padding: const EdgeInsets.all(10),
color: Colors.white,
child: Column(
children: [
Stack(
children: [
Align(
alignment: Alignment.topLeft,
child: Text(title),
),
Align(
alignment: Alignment.topRight,
//InkWellにはさまざまなクリックイベントやインタラクションイベントがあります
child: InkWell(
onTap: onTap,
child: const Icon(Icons.close),
),
),
],
),
const Divider(),
Container(
padding: const EdgeInsets.all(10),
width: double.infinity,
child: Text(content),
)
],
)),
),
);
}
}