How to display SnackBar in Flutter? - flutter

I want to display a SnackBar in my Flutter app. I have read the docs and copyed it:
The body of my scaffold:
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async => false,
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text("Osztályok"),
leading: Padding(
padding: const EdgeInsets.only(left: 5.0),
child: IconButton(
icon: Icon(Icons.exit_to_app, color: Colors.white70),
onPressed: () {
authService.signOut();
authService.loggedIn = false;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GoogleSignUp()));
})),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 5.0),
child: Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.add_circle_outline,
color: Colors.white70),
onPressed: () {
createPopup(context);
}),
// IconButton(
// icon: Icon(Icons.search, color: Colors.black38),
// onPressed: null),
],
)),
],
),
The SnackBarPage class:
class SnackBarPage extends StatelessWidget {
void jelszopress(TextEditingController jelszoController, BuildContext context) async{
var jelszo;
DocumentReference docRef =
Firestore.instance.collection('classrooms').document(globals.getid());
await docRef.get().then((value) => jelszo= (value.data['Jelszo']) );
if (jelszo == jelszoController.text.toString()){
Navigator.push(context,
MaterialPageRoute(builder: (context) => InClassRoom()));
}
else{
Navigator.pop(context);
final snackBar = SnackBar(content: Text('Yay! A SnackBar!'));
Scaffold.of(context).showSnackBar(snackBar);
}
}
Future<String> jelszoba(BuildContext context) {
TextEditingController jelszoController = TextEditingController();
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Add meg a jelszót'),
content: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
),
child: TextField(
controller: jelszoController,
decoration: InputDecoration(hintText: "Jelszó")
)
),
actions: <Widget>[
MaterialButton(
elevation: 5.0,
child: Text('Mehet'),
onPressed: () {
jelszopress(jelszoController, context);
},
)]);
}
);
}
var nevek;
var IDS;
SnackBarPage(this.nevek, this.IDS);
#override
Widget build(BuildContext context){
return ListView.builder(
itemCount: nevek.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
onTap: () {
globals.setid(IDS[index]);
jelszoba(context);
},
title: Text(nevek[index]),
),
);
},
) ;
}
}
But my cody doesn't display the SnackBar. I tried the solution of this question: How to properly display a Snackbar in Flutter? but adding a Builder widget didn't help.

"Scaffold.of(context)" has been deprecated, will return null. Now use "ScaffoldMessenger.of(context)". As per Flutter documentation.
#override
Widget build(BuildContext context) {
// here, Scaffold.of(context) returns null
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: const Text('snack'),
duration: const Duration(seconds: 1),
action: SnackBarAction(
label: 'ACTION',
onPressed: () { },
),
));
},
child: const Text('SHOW SNACK'),
),
),
);
}
NOTE: Make sure your main.dart overrided build() function should return "MaterialApp" as a widget, such as:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
// Must be MaterialApp widget for ScaffoldMessenger support.
return MaterialApp(
title: 'My App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyDashboard(),
);
}
}

So based on the error, it would seem that the context passed in Snackbar.of() is not the correct context. This would make sense based on 1 & 2; and summary copied below:
Each widget has its own BuildContext, which becomes the parent of the widget returned by the StatelessWidget.build or State.build function. (And similarly, the parent of any children for RenderObjectWidgets.)
In particular, this means that within a build method, the build context of the widget of the build method is not the same as the build context of the widgets returned by that build method.
So this means that the build context you are passing in jelszoba(context) function is not the build context you need and is actually the build context of the widget that is instantiating the Scaffold.
So How to Fix:
To fix this wrap your Card widget in your SnackbarPage in a Builder widget and pass the context from it, to the jelszoba(context) method.
An example from 1 I post below:
#override
Widget build(BuildContext context) {
// here, Scaffold.of(context) returns null
return Scaffold(
appBar: AppBar(title: Text('Demo')),
body: Builder(
builder: (BuildContext context) {
return FlatButton(
child: Text('BUTTON'),
onPressed: () {
// here, Scaffold.of(context) returns the locally created Scaffold
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('Hello.')
));
}
);
}
)
);
}

You can normally use snack bar in the Bottom Navigation bar in this way. However, if you want to show it in the body, then just copy the code from Builder and paste it in the body of the scaffold.
Scaffold(bottomNavigationBar: Builder(builder: (context) => Container(child: Row(children: <Widget>[
Icon(Icons.add_alarm), Icon(Icons.map), IconButton(icon: Icon(Icons.bookmark),
onPressed:() {
Scaffold.of(context).showSnackBar(mySnackBar);
final mySnackBar = SnackBar(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
behavior: SnackBarBehavior.floating,
backgroundColor: Colors.white, duration: Duration(seconds: 1),
content: Text(
'Article has been removed from bookmarks',
),);
}
),
],
),
),
),
);
Note: In the behaviour property of SnackBar, you can just leave it empty. But the problem with that is "If you have Curved Navigation Bar or you have a floating action button above the bottom navigation bar, then the snackbar will lift these icons (or FAB ) and will affect the UI". That's why SnackBar.floating is more preferred as it is more capatible with the UI.
But you can check and see on your own which suits you the best.

Related

showMaterialBanner doesnt hide on change route Looking up a deactivated widget's ancestor is unsafe

Cant close Material banner after closing the page that call it.
I two screen LoginScreen RecoverScreen, from LoginScreen the user open RecoverScreen to send recover password's email, if sent was done sucesfully i show MaterialBanner and pop RecoverScreen, in LoginScreen when i clic "Close" button in my Materialbanner i got the following error:
════════ Exception caught by gesture ═══════════════════════════════════════════
The following assertion was thrown while handling a gesture:
Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable.
To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.
When the exception was thrown, this was the stack
dart-sdk/lib/internal/js_dev_runtime/private/ddc_runtime/errors.dart 251:49 throw
packages/flutter/src/widgets/framework.dart 4032:9
packages/flutter/src/widgets/framework.dart 4045:14 [_debugCheckStateIsActiveForAncestorLookup]
ScaffoldMessenger.of(context).showMaterialBanner(
MaterialBanner(
padding: EdgeInsets.all(20),
content: Text('Recover password email was sended.'),
leading: Icon(Icons.info),
backgroundColor: Colors.green,
actions: <Widget>[
TextButton(
child: Text(
'Close',
style: TextStyle(color: Colors.white),
),
onPressed: () {
ScaffoldMessenger.of(context)
.hideCurrentMaterialBanner();
},
),
],
),
);
Try this full example:
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: LoginScreen(),
),
);
}
class LoginScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RecoverScreen(),
),
);
},
child: const Text('Recover password'),
)),
);
}
}
class RecoverScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
ScaffoldMessenger.of(context).showMaterialBanner(
MaterialBanner(
padding: const EdgeInsets.all(20),
content: const Text('Recover password email was sended.'),
leading: const Icon(Icons.info),
backgroundColor: Colors.green,
actions: <Widget>[
TextButton(
child: const Text(
'Cerrar',
style: TextStyle(color: Colors.white),
),
onPressed: () {
ScaffoldMessenger.of(context).hideCurrentMaterialBanner();
},
),
],
),
);
},
child: const Text('Send Password'),
)),
);
}
}
I know that in this case i can use a snackbar, but its only a example and i want to know how to deal with this problem.
Try wrapping the TextButton with Builder and pass the context of it instead of already closed RecoverScreen's.
actions: <Widget>[
Builder(
builder: (context) => TextButton(
child: const Text(
'Cerrar',
style: TextStyle(color: Colors.white),
),
onPressed: () {
ScaffoldMessenger.of(context).hideCurrentMaterialBanner();
},
),
),
],
Before route change call ScaffoldMessenger.of(context).clearMaterialBanners();
Like, here wrap Scaffold widget by WillPopScope,
Sample Code:
WillPopScope(
onWillPop: (){
ScaffoldMessenger.of(context).clearMaterialBanners();
Navigator.pop(context);
return;
},
child: ........
}
Here is how I solved it in Flutter 3.0.5
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
var c = Completer<bool>();
try {
ScaffoldMessenger.of(context).clearMaterialBanners();
ScaffoldMessenger.of(context).clearSnackBars();
c.complete(true);
} catch (e) {
c.completeError(e);
}
return c.future;
},
child: Scaffold(...),
);
}

No Scaffold widget found when use BottomSheet

I am just learning Flutter and got stuck on this error:
No Scaffold widget found.
Home widgets require a Scaffold widget ancestor.
The specific widget that could not find a Scaffold ancestor was: Home
The ancestors of this widget were
but as you can see from my code I do have a Scaffold and I played around adding it wherever I can but I didn't work for.
What can be the reason to what I've done or didn't notice there?
import 'package:firebase_redux_app/services/firebase.auth.dart';
import 'package:flutter/material.dart';
// import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_redux_app/services/firestore.dart';
import 'package:provider/provider.dart';
import 'package:firebase_redux_app/screens/home/brewList.dart';
import 'package:firebase_redux_app/models/brew.dart';
class Home extends StatelessWidget {
final AuthService _auth = AuthService();
#override
Widget build(BuildContext context) {
void _showSettingsPanel() {
showBottomSheet(
context: context,
builder: (context) {
return Container(
padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 60.0),
child: Text('bottom sheet'),
);
});
}
return StreamProvider<List<Brew>>.value(
value: DBFirestore().brews,
child: Scaffold(
backgroundColor: Colors.brown[50],
appBar: AppBar(
title: Text('Brew Crew'),
backgroundColor: Colors.brown[400],
elevation: 0.0,
actions: <Widget>[
FlatButton.icon(
onPressed: () async {
await _auth.signOut();
},
icon: Icon(Icons.person),
label: Text('Log Out')),
FlatButton.icon(
icon: Icon(Icons.settings),
label: Text('settings'),
onPressed: () => _showSettingsPanel(),
)
],
),
body: BrewList(),
),
);
}
}
This error is caused because of the scope of your _showSettingsPanel method
There are 2 things you can do
1.
Make the _showSettingsPanel a method in the Home class and allow it take the context as a parameter. Hence, wrap your settings FlatButton in a Builder and pass the context to the _showSettingsPanel method.
Like this
class Home extends StatelessWidget {
void _showSettingsPanel(context) {
showBottomSheet(
context: context,
builder: (context) {
return Container(
padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 60.0),
child: Text('bottom sheet'),
);
});
}
#override
Widget build(BuildContext context) {
return StreamProvider<List<Brew>>(
value: DBFireStore().brews
child: Scaffold(
backgroundColor: Colors.brown[50],
appBar: AppBar(
title: Text('Brew Crew'),
backgroundColor: Colors.brown[400],
elevation: 0.0,
actions: <Widget>[
FlatButton.icon(
onPressed: () async {
},
icon: Icon(Icons.person),
label: Text('Log Out')),
Builder(
builder: (context) {
return FlatButton.icon(
icon: Icon(Icons.settings),
label: Text('settings'),
onPressed: () => _showSettingsPanel(context),
);
}
)
],
),
body: BrewList(),
),
);
}
}
2.
Wrap the Home widget in a Scaffold wherever you use it, instead of using just Home
Like this
Scaffold(body: Home())
now this prb has different solutions. U gotta use sccafoldKey
final _scaffoldKey = GlobalKey<ScaffoldState>();
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
actions: [
IconButton(
onPressed: () {
_scaffoldKey.currentState!.showBottomSheet(
(context) => const AddTaskScreen());
},
icon: const Icon(Icons.add))
],
),

flutter setstate rebuild only one child

in flutter I need that when I call setstate, it only rebuilds a widget
I put 2 children in a stack, I need that when a button is pressed, only the second one is rebuilt.
bool popup = false;
Scaffold(
appBar: AppBar(
title: const Text('TEST'),
actions: <Widget>[
IconButton( // + BUTTON
icon: Icon(Icons.add),
onPressed: () {
setState(() {
popup = true;
});
},
),
IconButton( // - BUTTON
icon: Icon(Icons.remove),
onPressed: () {
setState(() {
popup = false;
});
),
],
),
body: SafeArea(
child: Stack(
children: <Widget>[
Container( // FIRST WIDGET
key: ValueKey(1),
child: Text("Random - "+new Random().nextInt(20).toString())
),
popup ? Center(child: Text("abc")) : Text("") , // SECOND WIDGET
],
),
),
);
I expect that when I press the "+" button only the second widget will be re-built, but now it will rebuild all the contents of the stack.
thank you all.
From the official docs we can read:
"When setState() is called on a State, all descendent widgets rebuild. Therefore, localize the setState() call to the part of the subtree whose UI actually needs to change. Avoid calling setState() high up in the tree if the change is contained to a small part of the tree."
My suggestion, and I use it most of the times, is separate the widget that you want to rebuild in a new StatefulWidget. This way the setState only will be rebuild that widget.
class MyAppBar extends StatefulWidget
...
class _MyAppBarState extends State<MyAppBar> {
bool popup = false;
#override
Widget build(BuildContext context) {
return AppBar(
title: const Text('TEST'),
actions: <Widget>[
IconButton( // + BUTTON
icon: Icon(Icons.add),
onPressed: () {
setState(() {
popup = true;
});
},
),
IconButton( // - BUTTON
icon: Icon(Icons.remove),
onPressed: () {
setState(() {
popup = false;
});
),
],
),
}
Then call it in your Scaffold:
Scaffold(
appBar: MyAppBar(),
Other method I can suggest is using ValueNotifier or notifyListeners(). Please read this page Avoid rebuilding all the widgets repetitively. It is well explained.
Another option is to use ValueListenableBuilder:
class _MyHomePageState extends State<MyHomePage> {
final ValueNotifier<bool> popup = ValueNotifier<bool>(false);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('TEST'),
actions: <Widget>[
IconButton(
// + BUTTON
icon: Icon(Icons.add),
onPressed: () {
popup.value = true;
}),
IconButton(
// - BUTTON
icon: Icon(Icons.remove),
onPressed: () {
popup.value = false;
})
],
),
body: Center(
child: ValueListenableBuilder<bool>(
valueListenable: popup,
builder: (context, value, _) {
return Stack(
children: [
Text("Random - " + new Random().nextInt(20).toString()),
popup.value ? Center(child: Text("abc")) : Text(""),
],
);
}),
),
);
}
}
You can use StreamBuilder:
StreamController<bool> popup = StreamController<bool>();
#override
void dispose() {
popup.close();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('TEST'),
actions: <Widget>[
IconButton( // + BUTTON
icon: Icon(Icons.add),
onPressed: () => popup.add(true),
),
IconButton( // - BUTTON
icon: Icon(Icons.remove),
onPressed: () => popup.add(false),
),
],
),
body: SafeArea(
child: Stack(
children: <Widget>[
Container( // FIRST WIDGET
key: ValueKey(1),
child: Text("Random - "+new Random().nextInt(20).toString())
),
StreamBuilder<bool>(
stream: popup.stream,
initialData: false,
builder: (cxt, snapshot) {
return snapshot.data ? Center(child: Text("abc")) : Text("");
},
)
],
),
),
);
}
Remove the setState from the widget you don't want to be changed. And only use setState for the ones you need to rebuild
Or you can consider using inheritedModel widget
Here is the example from where you can learn how to build an Inherited model widget to update only specific widgets rather than the whole widgets.
https://medium.com/flutter-community/flutter-state-management-setstate-fn-is-the-easiest-and-the-most-powerful-44703c97f035

Show Flutter's SnackBar above a visible Drawer menu?

I have a Scaffold with a simple Drawer in which I show a menu where a user can press a button. When this button is pressed I want to display a SnackBar, but the SnackBar is always displayed behind the Drawer. Is there some way to show it in front of the Drawer?
The drawer's code looks like:
class MyDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Drawer(
child: ListView(
children: <Widget>[
ListTile(
leading: Icon(Icons.lock_open),
title: Text('Click Me'),
onTap: () {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text(
'Test.',
)));
},
),
],
),
);
}
}
and it is used directly in the Scaffold:
return Scaffold(
drawer: MyDrawer(),
[...]
They said Drawer must be on the top of UI under MaterialDesign rules. But if you wanna such behaviour too much you can write own SnackBar.
static void showSnackBarAsBottomSheet(BuildContext context, String message)
{
showModalBottomSheet<void>(
context: context,
barrierColor: const Color.fromRGBO(0, 0, 0, 0),
builder: (BuildContext context) {
Future.delayed(const Duration(seconds: 5), () {
try {
Navigator.pop(context);
} on Exception {}
});
return Container(
color: Colors.grey.shade800,
padding: const EdgeInsets.all(12),
child: Wrap(children: [
Text(
message,
style:
GoogleFonts.robotoCondensed().copyWith(color: Colors.white),
)
]));
},
);
}
I've solved it by adding one more Scaffold inside Drawer and making its background transparent:
return Scaffold(
drawer: Scaffold(
backgroundColor: Colors.transparent,
body: MyDrawer(),
[...]

Snackbar in SimpleDialog Flutter

I faced an error code below when adding a snackbar to an on-pressed method in my Simpledialog.
[Scaffold.of() called with a context that does not contain a Scaffold.]
I would like to seek your advice on how to provide the correct context to resolve it.
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new AlertApp()));
}
class AlertApp extends StatefulWidget {
#override
_AlertAppState createState() => _AlertAppState();
}
class _AlertAppState extends State<AlertApp> {
SimpleDialog _simdalog;
void sDialog(){
_simdalog = new SimpleDialog(
title: new Text("Add To Shopping Cart"),
children: <Widget>[
new SimpleDialogOption(
child: new Text("Yes"),
onPressed: (){
final snackBar = SnackBar(content: Text('Purchase Successful'));
Scaffold.of(context).showSnackBar(snackBar);
},
),
new SimpleDialogOption(
child: new Text("Close"),
onPressed:() {Navigator.pop(context);},
),
],
);
showDialog(context: context, builder: (BuildContext context){
return _simdalog;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: new Center(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new RaisedButton(
child: new Text("Add to Shopping Cart [Simple]"),
onPressed:(){
sDialog();
}),
],
),
),
);
}
}
Solution 1: as Mazin Ibrahim mentioned in comments Scaffold.of() called with a context that does not contain a Scaffold
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
...
Scaffold(
key: _scaffoldKey,
...
onPressed: () {
_scaffoldKey.currentState.showSnackBar(
SnackBar(
content: Text('Purchase Successful'),
duration: Duration(seconds: 3),
));
}
Solution 2:
With package flushbar, you can also display notification on top
Flushbar link : https://github.com/AndreHaueisen/flushbar
Another suggestion to use flushbar How to show snackbar after navigator.pop(context) in Flutter?
Flushbar(
title: "Hey Ninja",
message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
flushbarPosition: FlushbarPosition.TOP,
flushbarStyle: FlushbarStyle.FLOATING,
reverseAnimationCurve: Curves.decelerate,
forwardAnimationCurve: Curves.elasticOut,
backgroundColor: Colors.red,
boxShadows: [BoxShadow(color: Colors.blue[800], offset: Offset(0.0, 2.0), blurRadius: 3.0)],
backgroundGradient: LinearGradient(colors: [Colors.blueGrey, Colors.black]),
isDismissible: false,
duration: Duration(seconds: 4),
icon: Icon(
Icons.check,
color: Colors.greenAccent,
),
mainButton: FlatButton(
onPressed: () {},
child: Text(
"CLAP",
style: TextStyle(color: Colors.amber),
),
),
showProgressIndicator: true,
progressIndicatorBackgroundColor: Colors.blueGrey,
titleText: Text(
"Hello Hero",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 20.0, color: Colors.yellow[600], fontFamily: "ShadowsIntoLightTwo"),
),
messageText: Text(
"You killed that giant monster in the city. Congratulations!",
style: TextStyle(fontSize: 18.0, color: Colors.green, fontFamily: "ShadowsIntoLightTwo"),
),
)..show(context);
You can return a bool from the showDialog method and use that to determine whether to show the snackbar:
void main() {
runApp(MaterialApp(
home: AlertApp(),
));
}
class AlertApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
MyShoppingButton(),
],
),
),
);
}
}
// Separate out the button from _AlertAppState so that the call to
// showSnackBar comes from a different BuildContext
class MyShoppingButton extends StatelessWidget {
#override
Widget build(BuildContext context) {
return RaisedButton(
child: Text("Add to Shopping Cart [Simple]"),
// Use an async onPressed method so that we can wait for the
// result from the dialog before deciding whether to show the snackbar
onPressed: () async {
bool result = await showDialog<bool>(
context: context,
builder: (BuildContext context) {
return MyShoppingDialog();
},
);
// Check if result is null below as Flutter will throw Exception if
// tries determining whether to enter an if branch will a null boolean
if (result != null && result) {
final snackBar = SnackBar(content: Text('Purchase Successful'));
Scaffold.of(context).showSnackBar(snackBar);
}
},
);
}
}
class MyShoppingDialog extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SimpleDialog(
title: Text("Add To Shopping Cart"),
children: <Widget>[
SimpleDialogOption(
child: Text("Yes"),
onPressed: () {
// Pop with a result of true so that MyShoppingButton
// knows to show snackbar. In any other case
// (including the user dismissing the dialog), MyShoppingButton
// null receive null, and so will not show the snackbar
Navigator.of(context).pop(true);
},
),
SimpleDialogOption(
child: Text("Close"),
onPressed: () {
Navigator.pop(context);
},
),
],
);
}
}
You should create a Scaffold widget inside of showDialog and a Builder widget as child of the Scaffold and pass context as parameter.
void sDialog({BuildContext context}){
_simdalog = new SimpleDialog(
title: new Text("Add To Shopping Cart"),
children: <Widget>[
new SimpleDialogOption(
child: new Text("Yes"),
onPressed: (){
final snackBar = SnackBar(content: Text('Purchase Successful'));
Scaffold.of(context).showSnackBar(snackBar);
},
),
new SimpleDialogOption(
child: new Text("Close"),
onPressed:() {Navigator.pop(context);},
),
],
);
showDialog(context: context, builder: (BuildContext context){
return GestureDetector(
onTap: (){Navigator.of(context).pop();},
child: Scaffold(
body: Builder(
builder: (context){
return _simdalog(context: context);
}
),
),);
});
}