1

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

      ,);
  }


}

2 Answers 2

2

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,
    );
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

If the solution worked for you, please vote it and accept it :)
The two solutions are very good, yes. However I do not know how to vote, I am not sure I can do it as my rating is too low.
0

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,
      )
    ]
      ,);
  }
}

4 Comments

It does not work, and furthermore resets my list once I press....
I have edited my answer a bit. Check whether it works
No problem. Can you mark my solution as the correct answer? It would help someone else.
Actually I don't know how to do it as I am new here... I will try to look for it tomorrow

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.