Reputation: 45
I have a Stateful Widget
that has some buttons. On each button press, I want to show different types of Dialog
. I made a function for my Button and for each button I simply call that function.
Since I want to show different Dialog
on a different button press, I tried to pass the Dialog Widget
as a parameter of the button function and call that widget inside onPressed
. When I try to build the app it shows these errors.
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown building DialogPage(dirty, dependencies: [_InheritedTheme, _LocalizationsScope-[GlobalKey#e6799]], state: _DialogPageState#a5060):
setState() or markNeedsBuild() called during build.
This Overlay widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: Overlay-[LabeledGlobalKey<OverlayState>#8e4e3]
state: OverlayState#665ea(entries: [OverlayEntry#1cc53(opaque: true; maintainState: false), OverlayEntry#020ad(opaque: false; maintainState: true), OverlayEntry#1d32e(opaque: false; maintainState: false), OverlayEntry#9a4ae(opaque: false; maintainState: true), OverlayEntry#2728f(opaque: false; maintainState: false), OverlayEntry#33d56(opaque: false; maintainState: true)])
The widget which was currently being built when the offending call was made was: DialogPage
dirty
dependencies: [_InheritedTheme, _LocalizationsScope-[GlobalKey#e6799]]
state: _DialogPageState#a5060
The relevant error-causing widget was:
DialogPage file:///C:/Users/imsajib02/AndroidStudioProjects/Flutter/widgets/lib/main.dart:43:32
When the exception was thrown, this was the stack:
#0 Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:3896:11)
#1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:3911:6)
#2 State.setState (package:flutter/src/widgets/framework.dart:1168:14)
#3 OverlayState.insertAll (package:flutter/src/widgets/overlay.dart:344:5)
#4 OverlayRoute.install (package:flutter/src/widgets/routes.dart:44:24)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
════════ (2) Exception caught by widgets library ═══════════════════════════════════════════════════
The method 'drive' was called on null.
Receiver: null
Tried calling: drive<Color>(Instance of '_ChainedEvaluation<Color>')
The relevant error-causing widget was:
MaterialApp file:///C:/Users/imsajib02/AndroidStudioProjects/Flutter/widgets/lib/main.dart:11:12
════════════════════════════════════════════════════════════════════════════════════════════════════
════════ (3) Exception caught by widgets library ═══════════════════════════════════════════════════
'package:flutter/src/animation/animations.dart': Failed assertion: line 376 pos 15: 'parent != null': is not true.
The relevant error-causing widget was:
MaterialApp file:///C:/Users/imsajib02/AndroidStudioProjects/Flutter/widgets/lib/main.dart:11:12
════════════════════════════════════════════════════════════════════════════════════════════════════
D/FlutterView( 3883): Detaching from a FlutterEngine: io.flutter.embedding.engine.FlutterEngine@e78ea39
Class where the button widget is placed:
class DialogPage extends StatefulWidget {
@override
_DialogPageState createState() => _DialogPageState();
}
class _DialogPageState extends State<DialogPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Dialogs"),
),
body: Center(
child: SingleChildScrollView(
padding: EdgeInsets.only(top: 35),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
verticalDirection: VerticalDirection.down,
children: <Widget>[
Button("DEFAULT DIALOG", DialogCollection().defaultDialog(context)),
Button("DIALOG WITH ICON - 1", DialogCollection().customDialog_1(context)),
Button("Widget", DialogCollection().defaultDialog(context)),
Button("Widget", DialogCollection().defaultDialog(context)),
Button("Widget", DialogCollection().defaultDialog(context)),
Button("Widget", DialogCollection().defaultDialog(context)),
],
),
),
),
);
}
Button(String text, Widget widget) {
return Column(
children: <Widget>[
Container(
width: 230,
child: RaisedButton(
onPressed: () {
},
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(25.0),
//side: BorderSide(color: Colors.red)
),
color: Colors.blueGrey,
padding: EdgeInsets.only(top: 12.0, bottom: 12.0, left: 40.0, right: 40.0),
textColor: Colors.white,
child: Text(text, textAlign: TextAlign.center ,style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
),
),
Container(
height: 35,
)
],
);
}
}
class from where I call the dialog widgets:
class DialogCollection {
defaultDialog(BuildContext context) {
return showDialog(
context: context,
//barrierDismissible: false, //on touch outside does not dismiss the dialog
builder: (BuildContext context) {
return WillPopScope( //WillPopScope stops dismissing dialog on outside touch and back press
onWillPop: () {
Navigator.of(context).pop();
return null;
},
child: AlertDialog(
title: Text("Dialog Title", textAlign: TextAlign.center,),
titlePadding: const EdgeInsets.all(15.0),
titleTextStyle: TextStyle(
color: Colors.redAccent,
fontSize: 20,
fontWeight: FontWeight.bold,
),
content: Text("This is the description of the dialog."),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
color: Colors.lightBlueAccent,
textColor: Colors.white,
child: Text("Yes", style: TextStyle(
fontSize: 18,
),
),
),
FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
color: Colors.redAccent,
textColor: Colors.white,
child: Text("No", style: TextStyle(
fontSize: 18,
),
),
),
],
),
);
}
);
}
}
Upvotes: 0
Views: 1445
Reputation: 54407
You can copy paste run full code below
DialogCollection().defaultDialog(context)
means execute this function
You can call Button
with DialogCollection().defaultDialog
to pass function address and pass context
code snippet
Button("DEFAULT DIALOG", DialogCollection().defaultDialog, context)
Button(String text, Function callback, BuildContext context) {
return Column(
children: <Widget>[
Container(
width: 230,
child: RaisedButton(
onPressed: () {
callback(context);
},
working demo
full code
import 'package:flutter/material.dart';
class DialogCollection {
defaultDialog(BuildContext context) {
return showDialog(
context: context,
//barrierDismissible: false, //on touch outside does not dismiss the dialog
builder: (BuildContext context) {
return WillPopScope(
//WillPopScope stops dismissing dialog on outside touch and back press
onWillPop: () {
Navigator.of(context).pop();
return null;
},
child: AlertDialog(
title: Text(
"Dialog Title",
textAlign: TextAlign.center,
),
titlePadding: const EdgeInsets.all(15.0),
titleTextStyle: TextStyle(
color: Colors.redAccent,
fontSize: 20,
fontWeight: FontWeight.bold,
),
content: Text("This is the description of the dialog."),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
color: Colors.lightBlueAccent,
textColor: Colors.white,
child: Text(
"Yes",
style: TextStyle(
fontSize: 18,
),
),
),
FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
color: Colors.redAccent,
textColor: Colors.white,
child: Text(
"No",
style: TextStyle(
fontSize: 18,
),
),
),
],
),
);
});
}
}
class DialogPage extends StatefulWidget {
@override
_DialogPageState createState() => _DialogPageState();
}
class _DialogPageState extends State<DialogPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Dialogs"),
),
body: Center(
child: SingleChildScrollView(
padding: EdgeInsets.only(top: 35),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
verticalDirection: VerticalDirection.down,
children: <Widget>[
Button(
"DEFAULT DIALOG", DialogCollection().defaultDialog, context),
//Button("DIALOG WITH ICON - 1", DialogCollection().customDialog_1(context)),
/* Button("Widget", DialogCollection().defaultDialog(context)),
Button("Widget", DialogCollection().defaultDialog(context)),
Button("Widget", DialogCollection().defaultDialog(context)),
Button("Widget", DialogCollection().defaultDialog(context)),*/
],
),
),
),
);
}
Button(String text, Function callback, BuildContext context) {
return Column(
children: <Widget>[
Container(
width: 230,
child: RaisedButton(
onPressed: () {
callback(context);
},
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(25.0),
//side: BorderSide(color: Colors.red)
),
color: Colors.blueGrey,
padding: EdgeInsets.only(
top: 12.0, bottom: 12.0, left: 40.0, right: 40.0),
textColor: Colors.white,
child: Text(
text,
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
),
),
Container(
height: 35,
)
],
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: DialogPage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Upvotes: 1