How to call flutter dialog from separate class? - flutter

I need to separate my dialog to separate widgets an call from anywhere on some button click. Now my code looks like:
import 'package:flutter/material.dart';
class PlacesListScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return _Map();
}
}
class _Map extends StatefulWidget {
#override
_MapState createState() => _MapState();
}
class _MapState extends State<_Map> {
final _titleController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('App name'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
onPressed: () {
return showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text(
"Dialog title",
textAlign: TextAlign.center,
),
content: TextField(
decoration: InputDecoration(labelText: 'Title'),
controller: _titleController,
),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.of(ctx).pop();
},
child: Text("No"),
),
FlatButton(
onPressed: () {
return showDialog(
context: context,
builder: (ctx) => StatefulBuilder(builder:
(BuildContext context, StateSetter setState) {
return AlertDialog(
title: Text(
"Second subdialog title",
textAlign: TextAlign.center,
),
content: Container(
width: 150,
height: 200,
decoration: BoxDecoration(
border:
Border.all(width: 1, color: Colors.grey),
),
child: Text('Here will be file'),
alignment: Alignment.center,
),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.of(ctx).pop();
},
child: Text("No"),
),
FlatButton(
onPressed: () => Text('Here I will work with state'),
child: Text("Yes"),
),
],
);
}),
);
},
child: Text("Yes"),
),
],
),
);
},
),
],
),
body: Text('App body here'),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
FloatingActionButton(
onPressed: () => Text('Here will be called dialog function'),
child: Icon(Icons.add, color: Colors.white),
backgroundColor: Colors.green,
heroTag: 'mapZoomIn',
),
],
),
);
}
}
Now how I can this part of code (calling dialog) separate to another widget and call then using created widget.
showDialog(
context: context,
builder: (ctx) => StatefulBuilder(builder:
(BuildContext context, StateSetter setState) {
return AlertDialog(
title: Text(
"Second subdialog title",
textAlign: TextAlign.center,
),
content: Container(
width: 150,
height: 200,
decoration: BoxDecoration(
border:
Border.all(width: 1, color: Colors.grey),
),
child: Text('Here will be file'),
alignment: Alignment.center,
),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.of(ctx).pop();
},
child: Text("No"),
),
FlatButton(
onPressed: () => Text('Here I will work with state'),
child: Text("Yes"),
),
],
);
}),
);

Firstly, you can refactor your StatefulBuilder(builder: (BuildContext context, StateSetter setState) { return AlertDialog(... into one separate widget like MyFancyDialog extends StatefulWidget. Then just call showDialog(..., MyFancyWidget()) when you need it.
Secondly, if you do not want the first method, you can extract the whole showDialog(...) into a function like void showMyFancyDialog() { showDialog... }. Is it also OK, since in dart functions are first class.

Did you try to create a new Stateful widget class at the bottom of your code and try to call that widget? If you didn't try that,
Go to under of your code and create a new Stateful class. (Let's say that myDialog)
Add the code that you want to call, inside of your "myDialog" widget
Go for where you want to call that code and try to call that class.
Hope this works for you.

Create a separate file. Import material package.
then create "Widget myDialog(context){ // paste your showDialog code here }"
Now your myDialog widget has been ready for using anywhere on whole project just import and call it.
When you call it pass BuildContext in its argument.
Its work for me.

Related

showModalBottomSheet Function onClose

I want to add a function when the showModalBottomSheet is close or when the barrier tapped the function run(routing to the main page) but how?
I want to run this when the barrier tapped/modal closed
Navigator.pushNamedAndRemoveUntil(context, '/mainMenuPage', (route) => false);
Modal Code
showModalBottomSheet(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(25.0),
),
),
backgroundColor: Colors.white,
context: context,
builder: (context) => Widget(...),
);
}
Try below code hope its help to you.
Your Widget with bottomSheet:
Center(
child: ElevatedButton(
child: const Text('showModalBottomSheet'),
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
color: Colors.amber,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('Modal BottomSheet'),
],
), //MyWidget()
),
);
},
).then(
(value) => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MyWidget(),
),
),
);
},
),
),
Other class:
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Center(
child: Text(
'Hello, World!',
style: Theme.of(context).textTheme.headline4,
),
),
);
}
}
.then() -> This means that the next instructions will be executed. But it allows you to execute the code when the asynchronous method completes.
showModalBottomSheet(
context: context,
builder: (context){
return Text("example");
}
).then((value) => {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => const Page2()))
});
You can try like this.

How to call alertdialog from another file? using flutter

how do I call the alert dialog from another dart file, when the user clicks the button in addstudents.dart, I want to make the alert dialog in another file just in case it can be reused? In my addstudents.dart i have this Container, please see the code below, thanks.
addstudents.dart
Container(
padding: EdgeInsets.only(top: 10),
width: (globals.screenWidth * 0.48),
height: (globals.screenHeight * 0.10),
decoration:
BoxDecoration(borderRadius: BorderRadius.circular(10)),
child: RaisedButton(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(10.0),
),
onPressed: () {
// calling another file dart
},
color: Colors.green,
child: RichText(
text: TextSpan(
text: "Confirmed!",
style: TextStyle(
fontWeight: FontWeight.bold,
fontFamily: "Nunito",
color: Colors.white,
fontSize: globals.fontsize_19)),
),
),
),
this is my alertdialog.dart
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Flutter'),
),
body: MyLayout()),
);
}
}
class MyLayout extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
child: Text('Show alert'),
onPressed: () {
showAlertDialog(context);
},
),
);
}
}
showAlertDialog(BuildContext context) {
Widget okButton = FlatButton(
child: Text("OK"),
onPressed: () {},
);
AlertDialog alert = AlertDialog(
title: Text("My title"),
content: Text("This is my message."),
actions: [
okButton,
],
);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
Dunno if this is the best practice but here's what I'm doing
class Alerts {
static showAlertDialog(BuildContext context) {
Widget okButton = FlatButton(
child: Text("OK"),
onPressed: () {},
);
AlertDialog alert = AlertDialog(
title: Text("My title"),
content: Text("This is my message."),
actions: [
okButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
}
I call them using Alerts.showAlertDialog(context);

Flutter - How can I reuse some code at multiple places

Hi I have a app where I will be making a book and this book will be with images,
I am trying to reuse code meaning how to add code within a method and than have that method at different areas but only change the image in each method .. .to make the code more reusable??? the code will stay the same but the image in each code block will change... i dont want to copy and paste the code again and again.
import 'dart:ui';
import 'package:adobe_xd/adobe_xd.dart';
import 'dart:io';
import 'package:Quran_highlighter/main.dart';
import 'package:flutter/rendering.dart';
import 'package:system_shortcuts/system_shortcuts.dart';
import 'package:Quran_highlighter/Widgets/NavDrawer.dart';
import 'package:flutter/material.dart';
import 'package:zoom_widget/zoom_widget.dart';
import 'package:flutter/gestures.dart';
import 'package:Quran_highlighter/Widgets/size_config.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
class Aliflaammeem extends StatefulWidget {
#override
_AliflaammeemState createState() => _AliflaammeemState();
}
class _AliflaammeemState extends State<Aliflaammeem> {
#override
Widget build(BuildContext context) {
var screenSizes = MediaQuery.of(context).size;
return Scaffold(
appBar: new AppBar(title: new Text("1 Alif-laam-meem آلم, Pg2")),
// return DefaultTextStyle(
// style: Theme.of(context).textTheme.bodyText2,
body: LayoutBuilder(builder:
(BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: Stack(children: <Widget>[
new Slidable(
delegate: new SlidableDrawerDelegate(),
actionExtentRatio: 0.10,
// body: Center,
child: SafeArea(
top: true,
bottom: true,
right: true,
left: true,
child: new Container(
**child: new Image.asset(
"test/assets/Para 1 - Alif-laam-meem no color/quranpg2.png",**
fit: BoxFit.cover,
),
),
),
actions: <Widget>[
new IconSlideAction(
caption: 'English',
// color: Colors.lightBlue,
color: Colors.blueGrey,
icon: Icons.language,
foregroundColor: Colors.lightBlue,
// color: Colors.black,
// ),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Changepg2topg3()),
);
}),
new IconSlideAction(
caption: 'Forward',
// color: Colors.greenAccent,
// color: Colors.black87,
icon: Icons.arrow_back_ios,
foregroundColor: Colors.greenAccent,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Changepg2topg3()),
);
}),
// ),
],
secondaryActions: <Widget>[
new IconSlideAction(
caption: 'Back',
// color: Colors.red[200],
icon: Icons.arrow_forward_ios,
foregroundColor: Colors.red[200],
// color: Colors.black87,
// onTap: () => _showSnackBar('More'),
),
new IconSlideAction(
caption: 'Arabic',
// color: Colors.yellow[800],
icon: Icons.brightness_4,
foregroundColor: Colors.yellow[800],
color: Colors.blueGrey,
// onTap: () =>
),
],
),
]));
}));
}
}
//I WANT THE TOP CODE TO BE THE GLOBAL CODE WHICH WILL REUSED AGAIN AND
AGAIN IN THE SAME CLASS - AND IF I CHANGE SOMETHING UP THERE, I WANT IT TO AUTOMATICALLY CHANGE THROUGHOUT ALL THE PAGES
AND BELOW WE HAVE THE SAME CODE WHICH I COPIED AND PASTED - AND JUST CHANGED THE IMAGE AND APPBAR TITLE.... I NEED TO SEE HOW I CAN ACHIEVE THIS WITHOUT COPY AND PASTING....
class Changepg2topg3 extends StatelessWidget {
#override
Widget build(BuildContext context) {
var screenSizes = MediaQuery.of(context).size;
return Scaffold(
appBar: new AppBar(title: new Text("1 Alif-laam-meem آلم, Pg3")),
// return DefaultTextStyle(
// style: Theme.of(context).textTheme.bodyText2,
body: LayoutBuilder(builder:
(BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: Stack(children: <Widget>[
new Slidable(
delegate: new SlidableDrawerDelegate(),
actionExtentRatio: 0.10,
// body: Center,
child: SafeArea(
top: true,
bottom: true,
right: true,
left: true,
child: new Container(
// padding: EdgeInsets.zero,
**child: new Image.asset(
`"test/assets/Para 1 - Alif-laam-meem no color/quranpg3.png",*`*
// fit: BoxFit.fitidth,
fit: BoxFit.cover,
),
),
),
actions: <Widget>[
new IconSlideAction(
caption: 'English',
color: Colors.lightBlue,
icon: Icons.language,
// onTap: () =>
),
new IconSlideAction(
caption: 'Forward',
color: Colors.greenAccent,
icon: Icons.arrow_back_ios,
// onTap: () => _showSnackBar('Share'),
),
],
secondaryActions: <Widget>[
new IconSlideAction(
caption: 'Back',
color: Colors.red[200],
icon: Icons.arrow_forward_ios,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Aliflaammeem()),
);
}),
// ),
new IconSlideAction(
caption: 'Arabic',
color: Colors.yellow[800],
icon: Icons.brightness_4,
// onTap: () =>
),
],
),
]));
// );
}));
}
}
// }
1.Make a class returning a list
2.Make a New Widget function and pass-in the list to this function

How did i setup popup AlertDialog?

How did i setup popup AlertDialog when int is equal or greater than 100?
showDialog(
context: _context,
builder: (BuildContext context) => AlertDialog(
title: Text("$_winner Won"),
)
);
void scoreTeamA() {
setState(() {
outputTeamA += _choiceA;
});
}
// I would like to show outputTeamA on the AlertDialog
Thank you
Mohammad
One way is to create a Widget for the AlertDialog and pass the String/Widget you want to show on that dialog.
class LoadingDialog{
static Future<void> showLoadingDialog(BuildContext context,String text) async {
return showDialog(
context: context,
builder: (BuildContext context){
return SimpleDialog(
children: <Widget>[
Center(
child: Container(
child: Column(
children: <Widget>[
SizedBox(
height:10,
),
Text(text),
]
),
),
),
],
),
}
);
}
}
then you can call on an Event like:
void scoreTeamA(){
outputTeamA += _choiceA;
LoadingDialog.showLoadingDialog(context, outputTeamA);
}
Note: this code might have some errors. i haven't tested this.
This is how I display an AlertDialog
showAlertDialog() {
return showDialog(
context: context,
builder: (context) => AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
side: BorderSide(color: Colors.redAccent, width: 2.0),
),
elevation: 6,
titlePadding: EdgeInsets.all(8.0),
titleTextStyle: TextStyle(
fontSize: 18, color: Colors.red, fontWeight: FontWeight.bold),
title: Text(
'This is the alert title',
textAlign: TextAlign.center,
),
contentPadding: EdgeInsets.all(8.0),
contentTextStyle: TextStyle(fontSize: 14, color: Colors.black),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text('Content...')
//content goes here
],
),
actions: <Widget>[
FlatButton(
onPressed: () => Navigator.of(context).pop(), child: Text('Okay'))
],
),
);
}
And then you would do your if check to check
if( outputTeamA >= 100){
showAlertDialog();
}
Of course you could use outputTeamA in AlertDialog

"Undefined name 'context'. Try correcting the name to one that is defined, or defining the name." Flutter

This is a snippet of my widgets.dart file where I defined a widget called see_all_cards and its only purpose is to show an extended list of all cards that I was initially displaying. It should just redirect to Trending.dart. That's my main goal here.
Widget see_all_cards(){
return Container(
child: FlatButton(
child: Text(
"See all (43)",
style: TextStyle(
color: Theme.of(context).accentColor, // error
),
),
onPressed: (){
Navigator.push(
context, // error
MaterialPageRoute(
builder: (BuildContext context){
return trending();
},
),
);
},
)
);
}
The following segment is my main page. I've called SlowlyApp from void main.
class SlowlyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SlowlyApp',
home: Scaffold(
appBar: AppBar(
title: Text('Search',
style: TextStyle(
color: Color.fromRGBO(0,0,0,1),
),
),
backgroundColor: Color.fromRGBO(225,225,0,1),
actions: <Widget>[
IconButton(
icon:
Icon(Icons.search),
onPressed: (){
showSearch(context: context, delegate: data_search());
}
),
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
smallgap(),
current_cards_heading(),
current_cards(),
see_all_cards(),
smallgap(),
],
),
),
);
}
}
see_all_cards should expect context as parameter. You only have context in your main widget's build method
Widget see_all_cards(BuildContext context){
return Container(
child: FlatButton(
child: Text(
"See all (43)",
style: TextStyle(
color: Theme.of(context).accentColor, // error
),
),
onPressed: (){
Navigator.push(
context, // error
MaterialPageRoute(
builder: (BuildContext context){
return trending();
},
),
);
},
)
);
}
And then you can call passing the context.
class SlowlyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SlowlyApp',
home: Scaffold(
appBar: AppBar(
title: Text('Search',
style: TextStyle(
color: Color.fromRGBO(0,0,0,1),
),
),
backgroundColor: Color.fromRGBO(225,225,0,1),
actions: <Widget>[
IconButton(
icon:
Icon(Icons.search),
onPressed: (){
showSearch(context: context, delegate: data_search());
}
),
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
smallgap(),
current_cards_heading(),
current_cards(),
see_all_cards(context),
smallgap(),
],
),
),
);
}
}
I also get this error to solve this way
it's the main file container called my widgets _buildFoodItem define context with parameters
Container(
height: MediaQuery.of(context).size.height - 185.0,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(75.0),
),
),
child: ListView(
primary: true,
padding: const EdgeInsets.only(left: 25.0, right: 20.0),
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 45.0),
child: Container(
height: MediaQuery.of(context).size.height - 300.0,
child: ListView(children: [
_buildFoodItem(context, 'assets/images/plate1.png',
'Slazmon bowl', '₹ 150:00'),
_buildFoodItem(context, 'assets/images/plate2.png',
'Spring bowl', '₹ 120:00'),
_buildFoodItem(context, 'assets/images/plate3.png',
'Chikz bowl', '₹ 100:00'),
_buildFoodItem(context, 'assets/images/plate4.png',
'Berry Bowl', '₹ 199:00'),
_buildFoodItem(context, 'assets/images/plate5.png',
'Greezy bowl', '₹ 170:00'),
]),
),
)
],
),
),
this is my widget _buildFoodItem check the context
Widget _buildFoodItem(
BuildContext context, String imgPath, String foodName, String price) {
return Padding(padding: const EdgeInsets.only(
top: 10.0, left: 10.0, right: 10.0),
child: InkWell(
onTap: () {
Navigator.push(
context,
(MaterialPageRoute(
builder: (context) => FoodDetailsPage(
heroTag: imgPath,
foodName: foodName,
foodPrice: price,
),
)));
},
))
}
)