I try to show an overlapping widget which is being added to a stack when the appropriate button is pressed. Here is simplified example of the code:
...
class _MyApp extends State<MyApp> {
bool _isFloatingWidgetShown = false;
@override
Widget build(BuildContext context) {
void _showFloatingWidget() {
setState(() {
_isFloatingWidgetShown = true;
});
}
void _hideFloatingWidget() {
setState(() {
_isFloatingWidgetShown = false;
});
}
return MaterialApp(
home: Scaffold(
body: Container(
child: Stack(
children: [
...
if (_isFloatingWidgetShown) MyFloatingWidget(onClose: _hideFloatingWidget)
]
...
class MyFloatingWidget extends StatefulWidget {
const MyFloatingWidget(
{Key? key, required this.onClose})
: super(key: key);
final Function onClose;
...
class _MyFloatingWidget extends State<MyFloatingWidget> {
@override
Widget build(BuildContext context) {
return IconButton(
onPressed: widget.onClose(),
icon: Icon(
Icons.close))
...
But once the widget is shown it immediately calls _hideFloatingWidget
method and I get the following error:
FlutterError (setState() or markNeedsBuild() called during build...
Why does it call assigned to onPressed
method by itself during state initialization?
CodePudding user response:
You should not use (if not necessary) functions in build method. When you do this, do not use setState in it. Just _showFloatingWidget and _hideFloatingWidget use out of the build method. "build" method is calling whenever you show the screen or when you use "setState". It calls the function because of it.
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
child: Stack(
children: [
...
if (_isFloatingWidgetShown) MyFloatingWidget(onClose: _hideFloatingWidget)
]
...
}
void _showFloatingWidget() {
setState(() {
_isFloatingWidgetShown = true;
});
}
void _hideFloatingWidget() {
setState(() {
_isFloatingWidgetShown = false;
});
}
CodePudding user response:
The solution is to use the following method notation for onPressed
property of IconButton:
...
onPressed: () {
widget.onClose();
}
...