Reputation: 29
I tried adding widgets dynamically using a button (Once it is pressed, a new Text widget is added to the widget tree).
It works partly, as my widget list (pwdWidgets) is updated once I press the button. However, I cannot see it on the screen whatsoever. I guess something is missing.
May someone give me a little tip to fix that?
I have attached my code
Regards
import 'package:flutter/material.dart';
class Add_Widgets extends StatefulWidget {
@override
_Add_WidgetsState createState() => _Add_WidgetsState();
}
class _Add_WidgetsState extends State<Add_Widgets> {
@override
Widget build(BuildContext context) {
return Scaffold(body: getbody(),);
}
var pwdWidgets = <Widget>[];
Widget AddWidgets(){
return MaterialButton(
child: Text("Add", style: TextStyle(color: Colors.black)),
onPressed: () {
pwdWidgets.add(Text("Hello World!"));
print(pwdWidgets);
});
}
Widget getbody(){
pwdWidgets=[AddWidgets()];
return Column(children:
pwdWidgets
,);
}
}
Upvotes: 1
Views: 2772
Reputation: 23
Okay there are basically two things you need to fix:
One is that you aren't updating the UI when you update your pwdWidgets. This can be done by setState((){});
, like so:
Widget AddWidgets(){
return MaterialButton(
child: Text("Add", style: TextStyle(color: Colors.black)),
onPressed: () {
setState((){
pwdWidgets.add(Text("Hello World!"));
});
print(pwdWidgets);
});
}
The other thing is that, even with setState, after every rebuild of the widget tree you initialise pwdWidgets to AddWidget, which is again just a single button. So instead, prefer to do that initialisation in initState
since initState only runs once and you need this initialisation also only once.
The complete fixed code is here:
class Add_Widgets extends StatefulWidget {
@override
_Add_WidgetsState createState() => _Add_WidgetsState();
}
class _Add_WidgetsState extends State<Add_Widgets> {
@override
Widget build(BuildContext context) {
return Scaffold(body: getbody(),);
}
var pwdWidgets = <Widget>[];
@override
initState(){
pwdWidgets=[AddWidgets()];
super.initState();
}
Widget AddWidgets(){
return MaterialButton(
child: Text("Add", style: TextStyle(color: Colors.black)),
onPressed: () {
setState((){pwdWidgets.add(Text("Hello World!"));});
print(pwdWidgets);
});
}
Widget getbody(){
return Column(children:
pwdWidgets,
);
}
}
Upvotes: 2
Reputation: 752
The widget is updated in the widget tree because the value of the variable is changed but the UI is not re-rendered for that change to reflect.
Setstate will solve this.
Widget AddWidgets(){
return MaterialButton(
child: Text("Add", style: TextStyle(color: Colors.black)),
onPressed: () {
pwdWidgets.add(Text("Hello World!"));
setState(() { pwdWidgets=pwdWidgets; });
print(pwdWidgets);
});
}
Edit:
Even after setsate it didn't work. Because each time the UI is rendered you are initializing the pwdWidgets back to only AddWidgets() here:
pwdWidgets=[AddWidgets()];
So I made quite a few changes in getbody() with two columns.
class Add_Widgets extends StatefulWidget {
@override
_Add_WidgetsState createState() => _Add_WidgetsState();
}
class _Add_WidgetsState extends State<Add_Widgets> {
@override
Widget build(BuildContext context) {
return Scaffold(body: getbody(),);
}
var pwdWidgets = <Widget>[];
Widget AddWidgets(){
return MaterialButton(
child: Text("Add", style: TextStyle(color: Colors.black)),
onPressed: () {
pwdWidgets.add(Text("Hello World!"));
setState(() {
pwdWidgets=pwdWidgets;
});
print(pwdWidgets);
});
}
Widget getbody(){
return Column(children:[
AddWidgets(),
Column(
children:pwdWidgets,
)
]
,);
}
}
Upvotes: 0