Toastのようにユーザーにメッセージを出して認識してもらうためのWidgetとしてSnackBarがあります
Androidでは、そのまま SnackBar というのがありますが、iOSには同じものはありません
似たものとしては、メッセージを表示するToastやUIAlertControllerがあります
SnackBar
最初に、SnackBarはこちらにあるようにScaffoldが重要になります
また、メッセージの表示以外のアクションをさせることも可能です
- Create a Scaffold
- Display a SnackBar
- Provide an optional action
「No ScaffoldMessenger widget found」のエラーが出る場合は #2 を確認してください
1. Create a Scaffold
1 2 3 4 5 6 7 8 9 |
return MaterialApp( // ここにScafforldがないとSnackBarが作れない home: Scaffold( appBar: AppBar( title: const Text('SnackBar'), ), body: const SnackBarPage(), ), ); |
2. Display a SnackBar
1 2 3 4 5 6 7 |
snackBar = SnackBar( content: Text('Yay! A SnackBar!'), duration: Duration(seconds: 3), ); // Widget tree から ScaffordMessenger を探して SnackBar を表示させるために使う ScaffoldMessenger.of(context).showSnackBar(snackBar); |
ここまでをまとめて
ボタンタップでSnackBarが表示されるコードはこのようになります
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
import 'package:flutter/material.dart'; void main() { runApp( const MainApp()); } class MainApp extends StatelessWidget { const MainApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( // ここにScafforldがないとSnackBarが作れない home: Scaffold( appBar: AppBar( title: const Text('SnackBar'), ), body: const SnackBarPage(), ), ); } } class SnackBarPage extends StatelessWidget{ const SnackBarPage({super.key}); @override Widget build(BuildContext context) { return Center( child: ElevatedButton( child: const Text('Show SnackBar'), onPressed: () { const snackBar = SnackBar( content: Text('Yay! A SnackBar!'), duration: Duration(seconds: 3), ); ScaffoldMessenger.of(context).showSnackBar(snackBar); }, ), ); } } |
スクリーン下にメッセージが表示されました
3. Provide an optional action
SnackBar の特徴として、単なるToastなどとは異なりボタンアクションなどを追加することができます
例えば、ボタンをタップしてSnackBarを表示させ
右端にButtonというテキストボタンを作成して
Textの表示を変えるアクションを入れるとこうなります
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
var message = 'OK?'; void changeText(){ setState((){ message = 'Yes!'; }); } ... ElevatedButton( child: const Text('Show SnackBar'), onPressed: () { var snackBar = SnackBar( content: Text('Yay! A SnackBar!'), duration: const Duration(seconds: 3), action: SnackBarAction( label: 'Button', onPressed: changeText, ), ); ScaffoldMessenger.of(context).showSnackBar(snackBar); }, ), |
サンプルコード
以上をまとめて、多少見やすくすると
main.dart
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
import 'package:flutter/material.dart'; void main() { runApp( const MainApp()); } class MainApp extends StatelessWidget { const MainApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( // ここにScafforldがないとSnackBarが作れない home: Scaffold( appBar: AppBar( title: const Text('SnackBar'), ), body: const SnackBarPage(), ), ); } } class SnackBarPage extends StatefulWidget{ const SnackBarPage({super.key}); @override State<SnackBarPage> createState() => _SnackBarPageState(); } class _SnackBarPageState extends State<SnackBarPage>{ var message = 'OK?'; void changeText(){ setState((){ message = 'Yes!'; }); } @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( message, style: const TextStyle( fontSize: 30, ) ), const SizedBox(height: 20), ElevatedButton( child: const Text( 'Show SnackBar', style: TextStyle( fontSize: 24, ) ), onPressed: () { var snackBar = SnackBar( content: const Text( 'Yay! A SnackBar!', style: TextStyle( fontSize: 18, ) ), duration: const Duration(seconds: 10), backgroundColor: Colors.blue, action: SnackBarAction( label: 'Button', onPressed: changeText, ), ); ScaffoldMessenger.of(context).showSnackBar(snackBar); }, ), ], ), ); } } |
Show SnackBar ボタンをタップして
スクリーン下にSnackBarが表示されます
右端の Button をタップすると
OK? からYes! にTextが変更され
SnackBarのActionが確認されます
No ScaffoldMessenger widget found
SnackBar でこのようなエラーになった場合、
No ScaffoldMessenger widget found.
MainApp widgets require a ScaffoldMessenger widget ancestor.
こちらに説明がありますが
SnackBarを表示するために必要な ScaffoldMessenger が
context の上位に存在しないとエラーになり
Scaffoldを正しく親ウィジェットとして配置する必要があるようです
ScaffoldMessenger.of(context).showSnackBar(snackBar);
この context が Scaffold の子Widgetであることを確認しないといけません
References:
SnackBar class
Display a snackbar
ScaffoldMessenger class