ShowDialog did not pop out - android

i have created global method that call showDialog, whenever i call it, it wont come out if i put Navigator.pop(context) , if i remove the navigator it will come out. I cannot close the errordialog if i dont have the navigator. Did i do something wrong? below is my code
class GlobalMethod {
static void showErrorDialog(
{required String error, required BuildContext ctx}) {
showDialog(
context: ctx,
builder: (context) {
return AlertDialog(
title: Row(children: [
Padding(
padding: EdgeInsets.all(8.0),
child: Icon(
Icons.logout,
color: Colors.grey,
size: 35,
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: Text('Error Occured'),
),
]),
content: Text(error,
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontStyle: FontStyle.italic)),
actions: [
TextButton(
onPressed: () {
Navigator.canPop(context) ? Navigator.canPop(context) : null;
},
child: Text(
'Okay',
style: TextStyle(
color: Colors.red,
),
),
)
],
);
});
}
This is example when i call the method. If i remove the Navigator.pop the error dialog will pop out, if i put the navigator.pop nothing will come out
else if (balance < price! ){
GlobalMethod.showErrorDialog(error: "you dont have enough balance , please top up first", ctx: context);
Navigator.pop(context);
}

You need to remove Navigator after the showErrorDialog:
else if (balance < price! ){
GlobalMethod.showErrorDialog(error: "you dont have enough balance , please top up first", ctx: context);
}
then change this in your showErrorDialog:
onPressed: () {
Navigator.canPop(context) ? Navigator.pop(context): null;
},
you are use canPop but you need to use pop for navigation, canPop just return you a bool result.

For the pop use Navigator.pop(context)
class GlobalMethod {
static void showErrorDialog(
{required String error, required BuildContext ctx}) {
showDialog(
context: ctx,
builder: (context) {
return AlertDialog(
title: Row(children: [
Padding(
padding: EdgeInsets.all(8.0),
child: Icon(
Icons.logout,
color: Colors.grey,
size: 35,
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: Text('Error Occured'),
),
]),
content: Text(error,
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontStyle: FontStyle.italic)),
actions: [
TextButton(
onPressed: () {
Navigator.canPop(ctx) ? Navigator.pop(context) : null;
},
child: Text(
'Okay',
style: TextStyle(
color: Colors.red,
),
),
)
],
);
});
}
}
Remove pop
else if (balance < price! ){
GlobalMethod.showErrorDialog(error: "you dont have enough balance , please top up first", ctx: context);
}

Related

I want to create bottom sheet dialog like this image below in flutter

Please help me!!!
I m new in flutter, i want to create like this in my flutter app on button click.
Try below code,
showModalBottomSheet(
context: context,
builder: (BuildContext cntx) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: Icon(Icons.camera),
title: Text("Camera"),
onTap: () async {
},
),
ListTile(
leading: Icon(Icons.image),
title: Text("Files")),
onTap: () async {
},
),
Container(
height: 50,
color: prefix0.appBackgroundColcor,
child: ListTile(
title: Center(
child: Text(
"Cancel",
style: TextStyle(color: Colors.white),
),
),
onTap: () {
Navigator.pop(context);
},
),
)
],
);
});
You can use cupertino bottom modal to achieve something like that. See below code for implementation:
void show() {
showCupertinoModalPopup(
context: context,
builder: (BuildContext cont) {
return CupertinoActionSheet(
actions: [
CupertinoActionSheetAction(
onPressed: () {
print('Camera');
},
child: Text('Use Camera'),
),
CupertinoActionSheetAction(
onPressed: () {
print('Upload files');
},
child: Text('Upload from files'),
),
CupertinoActionSheetAction(
onPressed: () {
print('Dropbox');
},
child: Text('Upload from DropBox'),
)
],
cancelButton: CupertinoActionSheetAction(
onPressed: () {
Navigator.of(cont).pop;
},
child: Text('Cancel', style: TextStyle(color: Colors.red)),
),
);
});
}
Call the show function with the press of any button. You will see something like this.
If you don't want the divider between actions you have to create your own custom popup.

Calling multiple functions in FutureBuilder causes an error

I am retrieving data from Firestore in the form of two functions (_onpressed() and _drname()) and called both of them in FutureBuilder.
Function 1 is
Future _onPressed() async {
if (widget.brew.id == currentid.userid()) {
return await db
.collection('Messages')
.doc(widget.brew.id)
.get()
.then((DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists) {
print('${documentSnapshot.data()['Message']}');
String msg = json.encode(documentSnapshot.data()['Message']);
return msg;
} else {
print('Document does not exist on the database');
}
// var a= documentSnapshot.data()['Message'];
});
} else {
return 'No Prescription from doctor yet';
}}
Function 2 is
Future _drname() async {
if (widget.brew.id == currentid.userid()) {
return await db
.collection('Drname')
.doc(widget.brew.id)
.get()
.then((DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists) {
print('${documentSnapshot.data()['name']}');
String msg = json.encode(documentSnapshot.data()['name']);
return msg;
} else {
print('Document does not exist on the database');
}
// var a= documentSnapshot.data()['Message'];
});
} else {
return 'No';
}}
Calling these functions in FutureBuilder like this
Widget _messagePannel() {
return FutureBuilder(
future: Future.wait([_onPressed(),_drname()]),
builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
return Scaffold(
appBar: AppBar(
actions: [
Padding(
padding: const EdgeInsets.only(right: 17.0),
child: TextButton.icon(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Call()),
);
},
icon: Icon(
Icons.video_call,
color: Colors.white,
size: 30.0,
),
label: Text(''),
),
)
],
title: Text(
'Prescrption',
style: TextStyle(fontFamily: 'RussoOne', fontSize: 22.0),
),
backgroundColor: Colors.green[900],
elevation: 0.0,
centerTitle: true,
),
body: Container(
decoration: image,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
color: Colors.black,
child: Center(
child: Padding(
padding: EdgeInsets.fromLTRB(0.0, 4.0, 4.0, 4.0),
child: Wrap(
children: [
Center(
child: Text(
'${snapshot.data[0]} ',
textAlign: TextAlign.left,
style: TextStyle(
fontFamily: 'RussoOne',
color: Colors.white,
letterSpacing: 0.8,
fontSize: 18.0,
backgroundColor: Colors.black),
),
),
Center(
child: Text(
'${snapshot.data[1]} ',
textAlign: TextAlign.left,
style: TextStyle(
fontFamily: 'RussoOne',
color: Colors.white,
letterSpacing: 0.8,
fontSize: 18.0,
backgroundColor: Colors.black),
),
),
],
),
)),
),
),
),
],
),
),
),
);
});}
Getting This error from the Debug Console
The following NoSuchMethodError was thrown building FutureBuilder<List>(dirty, state: _FutureBuilderState<List>#44f46):
The method '[]' was called on null.
Receiver: null
Tried calling:
When using snapshot, the initial value for the data property is null (since Future has no result until you receive the response), so using it straight away as you do it in the code (e.g. snapshot.data[1]) should be avoided.
To cope with that, first of all you should check if the data is not null. For that, snapshot has a dedicated method snapshot.hasData, for instance:
return FutureBuilder(
future: Future.wait([_onPressed(),_drname()]),
builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator(); // E.g. Show loader if there is no data yet
}
return Scaffold(...); // Return the widget you have now
},
);

How to enable and disable button in GridView using Flutter?

I have created buttons in grid view using flutter. Now I want to change color of button when I click on button. Same like active use in HTML. When I click on button then button should be show in active state and when I click on another button then first button will be disable and current button will be enable.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'My Mitsu',
style: TextStyle(color: Colors.black),
),
backgroundColor: Colors.white,
actions: <Widget>[
new RaisedButton(
child: new Text("Logout",
style: TextStyle(color: Colors.black, fontSize: 20.0)),
onPressed: () async {
log_out();
},
color: Colors.white,
)
],
),
backgroundColor: Colors.white,
body: Column(children: [
Expanded(
child: GridView.count(
crossAxisCount: countValue,
mainAxisSpacing: 35.0,
crossAxisSpacing: 35.0,
padding: const EdgeInsets.fromLTRB(20.0, 40.0, 40.0, 20.0),
childAspectRatio: (aspectWidth / aspectHeight),
children: <Widget>[
RaisedButton(
child: Text('Send Lift to Parking',
style: TextStyle(fontSize: 15.0)),
onPressed: () {
onPress(0);
showShortToast();
},
),
RaisedButton(
onPressed: () {
onPress(1);
showShortToast();
},
child: Text('Send Lift to 1st Floor',
style: TextStyle(fontSize: 15.0)),
),
RaisedButton(
onPressed: () {
onPress(2);
showShortToast();
},
child: Text('Send Lift to 2st Floor',
style: TextStyle(fontSize: 15.0)),
),
RaisedButton(
onPressed: () {
onPress(3);
showShortToast();
},
child: Text('Send Lift to 3st Floor',
style: TextStyle(fontSize: 15.0)),
),
RaisedButton(
onPressed: () {
onPress(4);
showShortToast();
},
child: Text('Send Lift to 4st Floor',
style: TextStyle(fontSize: 15.0)),
),
RaisedButton(
onPressed: () {
onPress(5);
showShortToast();
},
child: Text('Send Lift to 5st Floor',
style: TextStyle(fontSize: 15.0)),
),
RaisedButton(
onPressed: () {
onPress(6);
showShortToast();
},
child: Text('Send Lift to 6st Floor',
style: TextStyle(fontSize: 15.0)),
),
RaisedButton(
onPressed: () {
onPress(7);
showShortToast();
},
child: Text('Send Lift to 7st Floor',
style: TextStyle(fontSize: 15.0)),
),
],
),
),
]));
}
if you don't pass a function to the onPressed property of the button, the button will be automatically disabled,
(don't pass = passing null)
///button#1
FlatButton(
//change color according to state
color: button1Enabled? Colors.green:Colors.red;
onPressed: button1Enabled? (){ } : null;
)
///button#2
FlatButton(
onPressed: (){
setState(){
button1Enabled = !button1Enabled;
}
}
)
Create you button like this
RaisedButton(
onPressed: () {
onPressed(1);
},
color: currentIndex == 1 ? bottonColor : null,
child: Text('Send Lift to 1st Floor',
style: TextStyle(fontSize: 15.0)),
),
and create onPress fuction like this
onPressed(String floor) {
setState(() {
currentIndex = int.parse(floor);
bottonColor = Colors.red;
});
}
create two variable outside the class currentIndex and buttonColor
int currentIndex = 0;
Color bottonColor;
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
}
}

Flutter - change appbar icon when receiving notification

I am using FirebaseMessaging to push notifications on my app.
So I can handle these notification with this code :
firebaseMessaging.configure(
onLaunch: (Map<String, dynamic> msg) {
print("onLaunch called");
}, onResume: (Map<String, dynamic> msg) {
print("onResume called");
}, onMessage: (Map<String, dynamic> msg) {
print("onMessage called : " + msg.toString());
});
When I receive a notification, I want to display this little '1' on my icon in my appbar
My problem is : I don't know how to change my bell icon dynamically on my appbar for all pages (and I can't call setState in my appbar)
I think is pretty simple to solve your problem you only need to use a Stateful class and a custom icon as below snippet:
Widget myAppBarIcon(){
return Container(
width: 30,
height: 30,
child: Stack(
children: [
Icon(
Icons.notifications,
color: Colors.black,
size: 30,
),
Container(
width: 30,
height: 30,
alignment: Alignment.topRight,
margin: EdgeInsets.only(top: 5),
child: Container(
width: 15,
height: 15,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Color(0xffc32c37),
border: Border.all(color: Colors.white, width: 1)),
child: Padding(
padding: const EdgeInsets.all(0.0),
child: Center(
child: Text(
_counter.toString(),
style: TextStyle(fontSize: 10),
),
),
),
),
),
],
),
);
}
and later you can include this icon on your app bar(leading or action). As you can see the Text value change with any touch I used as base the example code when you start a new Flutter project it contains a method to count how many times you touch the floating button and change the state:
void _incrementCounter() {
setState(() {
_counter++;
});
}
I hope this helps you
this is my example
Basic Idea behind the notification badge
Using Stack and Positioned widgets we can stack the Text widget over the
IconButton to show the notification badge.
appBar: AppBar(
leading: IconButton(
icon: Icon(
_backIcon(),
color: Colors.black,
),
alignment: Alignment.centerLeft,
tooltip: 'Back',
onPressed: () {
},
),
title: Text(
"Title",
style: TextStyle(
color: Colors.black,
),
),
backgroundColor: Colors.white,
actions: <Widget>[
IconButton(
tooltip: 'Search',
icon: const Icon(
Icons.search,
color: Colors.black,
),
onPressed: _toggle,
),
new Padding(
padding: const EdgeInsets.all(10.0),
child: new Container(
height: 150.0,
width: 30.0,
child: new GestureDetector(
onTap: () {
},
child: Stack(
children: <Widget>[
new IconButton(
icon: new Icon(
Icons.shopping_cart,
color: Colors.black,
),
onPressed: () {
}),
ItemCount == 0
? new Container()
: new Positioned(
child: new Stack(
children: <Widget>[
new Icon(Icons.brightness_1,
size: 20.0, color: Colors.orange.shade500),
new Positioned(
top: 4.0,
right: 5.0,
child: new Center(
child: new Text(
ItemCount.toString(),
style: new TextStyle(
color: Colors.white,
fontSize: 11.0,
fontWeight: FontWeight.w500),
),
)),
],
)),
],
),
),
),
)
],
),
You have to create a custom drawable and set it as the Appbar icon and you have to paint the number as text in the custom drawable. This is already done for you in the following link.
How to make an icon in the action bar with the number of notification?
you can just create variable of type IconData and change it's value. you will get more idea about that after gone through below example.
import 'package:flutter/material.dart';
void main() => runApp(MyHome());
class MyHome extends StatefulWidget {
#override
_MyHomeState createState() => _MyHomeState();
}
class _MyHomeState extends State<MyHome> {
IconData _iconData= Icons.notifications;
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primaryColor: Color(0xffFF5555),
),
home: Scaffold(
appBar: new AppBar(
title: new Text("Title"),
actions: <Widget>[
Icon(_iconData)
],
),
body: Center(
child: new Text("Demo")
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.check_circle_outline),
onPressed: (){
if(_iconData == Icons.notifications){
setState(() {
_iconData = Icons.notifications_active;
});
}else{
setState(() {
_iconData = Icons.notifications;
});
}
}
),
),
);
}
}

How to dismiss an AlertDialog on a FlatButton click?

I have the following AlertDialog.
showDialog(
context: context,
child: new AlertDialog(
title: const Text("Location disabled"),
content: const Text(
"""
Location is disabled on this device. Please enable it and try again.
"""),
actions: [
new FlatButton(
child: const Text("Ok"),
onPressed: _dismissDialog,
),
],
),
);
How can I make _dismissDialog() dismiss said AlertDialog?
Navigator.pop() should do the trick. You can also use that to return the result of the dialog (if it presented the user with choices)
Navigator.of(context, rootNavigator: true).pop('dialog')
worked with me.
Navigator.pop(_)
worked for me, but the Flutter Team's gallery contains an example using:
Navigator.of(context, rootNavigator: true).pop()
which also works, and I am tempted to follow their lead.
If you don't want to return any result, use either of them:
Navigator.of(context).pop();
Navigator.pop(context);
But if you do want to return some result, see this
Example:
showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: Text('Wanna Exit?'),
actions: [
FlatButton(
onPressed: () => Navigator.pop(context, false), // passing false
child: Text('No'),
),
FlatButton(
onPressed: () => Navigator.pop(context, true), // passing true
child: Text('Yes'),
),
],
);
}).then((exit) {
if (exit == null) return;
if (exit) {
// user pressed Yes button
} else {
// user pressed No button
}
});
Generally Navigator.pop(context); works.
But If the application has multiple Navigator objects and dialogBox doesn't close, then try this
Navigator.of(context, rootNavigator: true).pop();
If you want to pass the result call, try
Navigator.pop(context,result);
OR
Navigator.of(context, rootNavigator: true).pop(result);
Navigator.of(dialogContext).pop() otherwise you can close page if you navigated from Master to Detail page
showDialog(
context: context,
builder: (dialogContext) {
return Dialog(
child: Column(
children: [
Text("Content"),
RaisedButton(
onPressed: () => Navigator.of(dialogContext).pop(),
child: Text("Close"),
)
],
),
);
},
);
Example of dismissing alert dialog on flat button click
RaisedButton(
onPressed: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Are you sure?'),
content: Text('Do you want to remove item?'),
actions: <Widget>[
FlatButton(
onPressed: () => Navigator.of(context).pop(false),// We can return any object from here
child: Text('NO')),
FlatButton(
onPressed: () => Navigator.of(context).pop(true), // We can return any object from here
child: Text('YES'))
],
)).then((value) =>
print('Selected Alert Option: ' + value.toString()));
},
child: Text('Show Alert Dialog'),
),
Above code have two unique things which is used to provide callback result of dialog
Navigator.of(context).pop(false) -- return false value when we pressed
NO Navigator.of(context).pop(true) -- return true value when we
pressed YES
Based on these return value, we can perform some operation outside of it or maintain the dialog status value
This works Prefectly
RaisedButton(
child: Text(
"Cancel",
style: TextStyle(color: Colors.white),
),
color: Colors.blue,
onPressed: () => Navigator.pop(context),
),
This worked for me Navigator.of(context, rootNavigator: true).pop('dialog').
Navigator.pop() just closes the current page/screen.
Creating a separate context for Alert Dialog would help.
showDialog(
context: context,
builder: (alertContext) => AlertDialog(
title: const Text("Location disabled"),
content: const Text(
"""Location is disabled on this device. Please enable it and try again."""),
actions: [
new FlatButton(
child: const Text("Ok"),
onPressed: () => Navigator.pop(alertContext),
),
],
),
);
Please use following for code to close dialog
RaisedButton(
onPressed: () { Navigator.of(context).pop();},
child: Text("Close",style: TextStyle(color: Colors.white), ),
color: Colors.black,
)
Use Navigator.pop(context);
Example
showDialog(
context: context,
child: new AlertDialog(
title: const Text("Location disabled"),
content: const Text(
"""
Location is disabled on this device. Please enable it and try again.
"""),
actions: [
new FlatButton(
child: const Text("Ok"),
onPressed: () {
Navigator.pop(context);
},
),
],
),
);
This answer works if you want to pop the dialog and navigate to another view. This part 'current_user_location' is the string the router need to know which view to navigate to.
FlatButton(
child: Text('NO'),
onPressed: () {
Navigator.popAndPushNamed(context, 'current_user_location');
},
),
This enough to dismisss dialog add inside Any callback like onpressed,ontap
Navigator.of(context).pop();
AlertDialog(
title: Center(child: Text("$title")),
insetPadding: EdgeInsets.zero,
titlePadding: EdgeInsets.only(top: 14.0, bottom: 4),
content: Container(
height: 50,
child: TextFormField(
controller: find_controller,
decoration: InputDecoration(
suffixIcon: context.watch<MediaProvider>().isChangeDialog
? IconButton(
onPressed: () {
clearController(find_controller);
},
icon: Icon(Icons.clear))
: null,
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.deepPurpleAccent)),
hintText: 'Id',
),
onChanged: (val) {
if (val.isNotEmpty)
context.read<MediaProvider>().isChangeDialog = true;
else
context.read<MediaProvider>().isChangeDialog = false;
},
),
),
actions: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(4.0),
child: OutlinedButton(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Align(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Icon(Icons.clear),
),
),
Text("Cancel")
],
),
onPressed: () {
context.read<MediaProvider>().isChangeDialog = false;
//========================this enough to dismisss dialog
Navigator.of(context).pop();
}),
),
Padding(
padding: const EdgeInsets.all(4.0),
child: ElevatedButton(
onPressed: context.watch<MediaProvider>().isChangeDialog
? () {
context.read<MediaProvider>().isChangeDialog = false;
okCallback;
}
: null,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Align(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Icon(Icons.check),
),
),
Text("OK")
],
)),
)
],
),
],
);
pass it in the showDialog
barrierDismissible : true
use get package.
then Get.back() to close Modal
For Closing Dialog
void cancelClick() {
Navigator.pop(context);
}
The accepted answer states how to dismiss a dialog using the Navigator Class. To dismiss a dialog without using Navigator you can set the onPressed event of the button to the following:
setState((){
thisAlertDialog = null;
});
In case the code above is not self-explanatory it is basically setting the Parent AlertDialog of the FlatButton to null, thus dismissing it.

Categories

Resources