I am new to flutter,Here I can't find why my snackbar is not showing in the ui.I tried exactly like the documentation .
Scaffold(
body: Center(
child: ElevatedButton(
child: const Text('Show SnackBar'),
onPressed: () {
final snackBar = SnackBar(
content: const Text('Yay! A SnackBar!'),
action: SnackBarAction(
label: 'Undo',
onPressed: () {},
),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
),
),
));
The problem is, that the call to ScaffoldMessenger.of(context).showSnackBar(snackBar) makes Flutter search the widget tree for ancestors of type ScaffoldMessenger and it's not able to find one.
This happens, because you pass in the BuildContext of the widget under which the Scaffold is declared. But it searches in the opposite direction.
One solution to this is, to wrap the call to ScaffoldMessenger.of in a Builder widget, wich introduces a new BuildContext. Then Flutter is able to find a ScaffoldMessenger in the widget tree and use it to show the SnackBar.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Demo',
home: Scaffold(
body: Center(
child: Builder(
builder: (context) {
return ElevatedButton(
child: const Text('Show SnackBar'),
onPressed: () {
final snackBar = SnackBar(
content: const Text('Yay! A SnackBar!'),
action: SnackBarAction(
label: 'Undo',
onPressed: () {},
),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
);
}
),
),
),
);
}
}
Check out the Builder documentation, it explains everything about those .of() methods: https://api.flutter.dev/flutter/widgets/Builder-class.html
This is a sample code for displaying SnackBar in flutter
import 'package:flutter/material.dart';
void main() => runApp(const SnackBarDemo());
class SnackBarDemo extends StatelessWidget {
const SnackBarDemo({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SnackBar Demo',
home: Scaffold(
appBar: AppBar(
title: const Text('SnackBar Demo'),
),
body: const SnackBarPage(),
),
);
}
}
class SnackBarPage extends StatelessWidget {
const SnackBarPage({super.key});
#override
Widget build(BuildContext context) {
return Center(
child: ElevatedButton(
onPressed: () {
final snackBar = SnackBar(
content: const Text('Yay! A SnackBar!'),
action: SnackBarAction(
label: 'Undo',
onPressed: () {
// Some code to undo the change.
},
),
);
// Find the ScaffoldMessenger in the widget tree
// and use it to show a SnackBar.
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
child: const Text('Show SnackBar'),
),
);
}
}
Photo:
Try the below code, You may missed forgot to wrap your scaffold
with MaterialApp();
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyWidget(),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
child: const Text('Show SnackBar'),
onPressed: () {
final snackBar = SnackBar(
content: const Text('Yay! A SnackBar!'),
action: SnackBarAction(
label: 'Undo',
onPressed: () {},
),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
),
),
);
}
}
Related
I have a class extends StatelessWidget. When try call SnackBars in Scaffold like:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
splashRadius: 18,
icon: const Icon(Icons.thumb_up),
tooltip: 'Like the app',
onPressed: () {
final SnackBar snackBar = SnackBar(
duration: const Duration(seconds: 1),
content: const Text('Registered as you like the application.'),
action: SnackBarAction(
label: 'Undo',
onPressed: () {},
),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
),
],
title: const Text('My Application'),),
body: const Center(
child: Text("Hello World!"),)
);
}
}
when run the application show error like:
Exception has occurred.
FlutterError (No ScaffoldMessenger widget found.
MyApp widgets require a ScaffoldMessenger widget ancestor.
The specific widget that could not find a ScaffoldMessenger ancestor was:
MyApp
The ancestors of this widget were:
[root]
Typically, the ScaffoldMessenger widget is introduced by the MaterialApp at the top of your application widget tree.)
Wrap your app in an MaterialApp, like
void main() => runApp(MaterialApp(home: MyApp()));
use this code
class MyApp extends StatefulWidget {
const MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
GlobalKey<ScaffoldMessengerState> key = GlobalKey<ScaffoldMessengerState>();
#override
Widget build(BuildContext context) {
return MaterialApp(
home: ScaffoldMessenger(
key: key,
child: Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
splashRadius: 18,
icon: const Icon(Icons.thumb_up),
tooltip: 'Like the app',
onPressed: () {
final snackBar = SnackBar(
content: Text(
"message",
// style: Theme.of(context).textTheme.regularWhite14,
),
duration: const Duration(seconds: 5),
action: SnackBarAction(
label: 'OK',
textColor: CustomColorScheme.whiteColor,
onPressed: () {},
),
);
key.currentState!.showSnackBar(snackBar);
},
),
],
title: const Text('My Application'),
),
body: const Center(
child: Text("Hello World!"),
)),
),
);
}
}
I found the answer from the youtube video as the following:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
final _scaffoldkey = GlobalKey<ScaffoldMessengerState>();
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
scaffoldMessengerKey: _scaffoldkey,
home: Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
splashRadius: 18,
icon: const Icon(Icons.thumb_up),
tooltip: 'Like the app',
onPressed: () {
final SnackBar snackBar = SnackBar(
duration: const Duration(seconds: 1),
content:
const Text('Registered as you like the application.'),
action: SnackBarAction(
label: 'Undo',
onPressed: () {},
),
);
ScaffoldMessengerState? scaffold = _scaffoldkey.currentState;
scaffold!.showSnackBar(snackBar);
},
),
],
title: const Text('My Application'),
),
body: const Center(
child: Text("Hello World!"),
),
),
);
}
}
I found the solution for the problem but first: why the error happened?
It Fails because ScaffoldMessenger.of(context) doesn't find anything above this widget's context.
the solution to use Builder class as follows:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
actions: <Widget>[
Builder(
builder: (BuildContext context) {
return IconButton(
splashRadius: 18,
icon: const Icon(Icons.thumb_up),
tooltip: 'Like the app',
onPressed: () {
final SnackBar snackBar = SnackBar(
duration: const Duration(seconds: 1),
content: const Text(
'Registered as you like the application.'),
action: SnackBarAction(
label: 'Undo',
onPressed: () {},
),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
);
},
),
],
title: const Text('My Application'),
),
body: const Center(
child: Text("Hello World!"),
)),
);
}
}
How do I set the height of SnackBar in Flutter?
I have this code from flutter documentation:
import 'package:flutter/material.dart';
void main() => runApp(const SnackBarDemo());
class SnackBarDemo extends StatelessWidget {
const SnackBarDemo({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SnackBar Demo',
home: Scaffold(
appBar: AppBar(
title: const Text('SnackBar Demo'),
),
body: const SnackBarPage(),
),
);
}
}
class SnackBarPage extends StatelessWidget {
const SnackBarPage({super.key});
#override
Widget build(BuildContext context) {
return Center(
child: ElevatedButton(
onPressed: () {
final snackBar = SnackBar(
content: const Text('Yay! A SnackBar!'),
action: SnackBarAction(
label: 'Action name',
onPressed: () {
// Some code to undo the change.
},
),
);
// Find the ScaffoldMessenger in the widget tree
// and use it to show a SnackBar.
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
child: const Text('Show SnackBar'),
),
);
}
}
And this is the result:
How do I prevent the snack bar to be that big?
I want the text and the action to be on the same line.
Thanks
You can put that button in content, like this:
onPressed: () {
final snackBar = SnackBar(
content: Row(
children: [
Expanded(
child: Text('Yay! A SnackBar!'),
),
TextButton(
onPressed: () {
if (mounted) { // <==== add this for hide snackBar
ScaffoldMessenger.of(context).hideCurrentSnackBar();
}
// Some code to undo the change.
},
child: Text(
'Action name',
style: TextStyle(color: Theme.of(context).primaryColor),
),
)
],
),
);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
}
This is automatic. If there is enough space for both message and action items, it will be shown on same line.
You can try changing the padding of Snackbar. You can try making it float but overall, it is there for responsiveness.
Here is how the framework calculates if items should be placed in single row or across multiple rows.
I have a text field. I need a snackbar to appear after the user has finished typing words into it after 300ms.Snackbar should appear in the middle of the screen. How can I make the snackbar appear 300ms after the user has stopped typing in the text field?
My code:
final textController = TextEditingController();
....
child: TextField(
controller: textController,
onChanged: (value) {},
)
Similar to other answer, but will appear after user stopped typing and not when user submits the TextField :
Timer? t;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: TextField(
onChanged: (v) {
t?.cancel();
t = Timer(const Duration(milliseconds: 300), () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('im a snackbar'),
),
);
});
},
),
),
);
}
Please check the following code and see if it helps.
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(const SnackBarDemo());
class SnackBarDemo extends StatelessWidget {
const SnackBarDemo({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SnackBar Demo',
home: Scaffold(
appBar: AppBar(
title: const Text('SnackBar Demo'),
),
body: const SnackBarPage(),
),
);
}
}
class SnackBarPage extends StatelessWidget {
const SnackBarPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Center(
child: Center(
child: TextField(
onEditingComplete: () {
final snackBar = SnackBar(
content: const Text('Yay! A SnackBar!'),
action: SnackBarAction(
label: 'Undo',
onPressed: () {
// Some code to undo the change.
},
),
);
Timer(Duration(milliseconds: 300), () {
ScaffoldMessenger.of(context).showSnackBar(snackBar);
});
},
),
),
);
}
}
I tried to make Dialog function on my app.
But the "No MaterialLocalizations found." error came out and it didn't open the popup window.
I don't know how to solve this issue even though I tried to find other references.
Please let me know how to fix this issue.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(OverApp());
}
class OverApp extends StatefulWidget {
#override
_OverAppState createState() => _OverAppState();
}
class _OverAppState extends State<OverApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('List'),
),
body: RaisedButton(
child: Text('Show Material Dialog'),
onPressed: _showMaterialDialog,
),
),
);
}
_showMaterialDialog() {
showDialog(
context: context,
builder: (_) => new AlertDialog(
title: new Text("Material Dialog"),
content: new Text("Hey!"),
actions: <Widget>[
FlatButton(
child: Text('Close me!'),
onPressed: () {
Navigator.of(context).pop();
},
)
],
));
}
}
You need to put the MaterialApp in runApp (or make another widget and put the Scaffold in its build and use this new widget as the home of the MaterialApp).
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: OverApp()));
}
class OverApp extends StatefulWidget {
#override
_OverAppState createState() => _OverAppState();
}
class _OverAppState extends State<OverApp> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('List'),
),
body: RaisedButton(
child: Text('Show Material Dialog'),
onPressed: _showMaterialDialog,
),
);
}
_showMaterialDialog() {
showDialog(
context: context,
builder: (_) => new AlertDialog(
title: new Text("Material Dialog"),
content: new Text("Hey!"),
actions: <Widget>[
FlatButton(
child: Text('Close me!'),
onPressed: () {
Navigator.of(context).pop();
},
)
],
));
}
}
Can I create something similar to Toasts in Flutter ?that that appear after an event and clickable toast
example of what i want :
here is an example from the docs,
class SnackBarDemo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SnackBar Demo',
home: Scaffold(
appBar: AppBar(
title: Text('SnackBar Demo'),
),
body: SnackBarPage(),
),
);
}
}
class SnackBarPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(
onPressed: () {
final snackBar = SnackBar(
content: Text('Yay! A SnackBar!'),
action: SnackBarAction(
label: 'Undo',
onPressed: () {
// Some code to undo the change.
},
),
);
// Find the Scaffold in the widget tree and use
// it to show a SnackBar.
Scaffold.of(context).showSnackBar(snackBar);
},
child: Text('Show SnackBar'),
),
)
}
}
also i would recommend using this package as it has more customization and you don't have to worry about the scaffold context.