Search code examples
listviewflutterdialogmapsshowdialog

Add item to ListView inside SimpleDialog in Flutter


I'm trying to create a SimpleDialog to choose tags with a button to add a new tag to the list. Tag colors and icons are mapped.

I managed to build a dialog with a default list but it does not update when pressing the last option (_addTagOption doesn't add a new tag to the ListView as intended).

Any ideas what I'm doing wrong?

Here is the relevant code:

void _showDialog() {
    Map<IconData, Color> tagMap = {
      Icons.work: Colors.blue[900],
      Icons.beach_access: Colors.lightGreen,
      Icons.local_dining: Colors.lightGreen,
      Icons.supervised_user_circle: Colors.green,
      Icons.people: Colors.green,
      Icons.favorite_border: Colors.green,
      Icons.directions_run: Colors.deepOrange,
      Icons.directions_car: Colors.blueGrey,
      Icons.hotel: Colors.deepPurpleAccent,
    };
    var tagIconList = tagMap.keys.toList();
    var tagColorList = tagMap.values.toList();

    List<String> tagNames = [
      'Work',
      'Relax',
      'Eating',
      'Family',
      'Friends',
      'Relationship',
      'Sport',
      'Transport',
      'Sleep'
    ];

    int itemCount = tagMap.length;
    _addTagOption(){
      setState(() {
        tagMap[Icons.laptop] = Colors.deepOrange;
        tagNames.add('Challenge');
        itemCount = itemCount + 1;
      });
    }

    showDialog(
        context: context,
        builder: (BuildContext context) {
          return SimpleDialog(
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.all(Radius.circular(10.0))),
              children: <Widget>[
            Container(
                width: double.maxFinite,
                child: ListView.builder(
                    itemCount: itemCount,
                    shrinkWrap: true,
                    itemBuilder: (BuildContext context, int itemCount) {
                      return SimpleDialogOption(
                          onPressed: () {
                            Navigator.of(context).pop();
                            setState(() {
                              displayTagColor = tagColorList[itemCount];
                              displayTagIcon = tagIconList[itemCount];
                            });
                          },
                          child: Row(
                            children: <Widget>[
                              Icon(
                                tagIconList[itemCount],
                                color: tagColorList[itemCount],
                              ),
                              Padding(
                                  padding: EdgeInsets.only(left: 25),
                                  child: Text(tagNames[itemCount]))
                            ],
                          ));
                    })),
            SimpleDialogOption(
              onPressed: () {
                setState(() {
                  _addTagOption();
                });
              },
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Icon(
                    Icons.add,
                    size: 25,
                    color: Color(0x8A000000),
                  ),
                  Padding(
                      padding: EdgeInsets.only(left: 5),
                      child: Text('ADD NEW', style: TextStyle(color: Color(0x8A000000)),))
                ],
              ),
            )
          ]);
        });
  }

Solution

  • demo

    SimpleDialog is already built so when you change the list/map it does change the values of variable but bot refected. Trying adding print to observe the values. Basically to redraw the SimpleDialog just pop SimpleDialog call again. Like this

    class TagScreen extends StatefulWidget {
      @override
      _TagScreenState createState() => _TagScreenState();
    }
    
    class _TagScreenState extends State<TagScreen> {
      Map<IconData, Color> tagMap = {
        Icons.work: Colors.blue[900],
        Icons.beach_access: Colors.lightGreen,
        Icons.local_dining: Colors.lightGreen,
        Icons.supervised_user_circle: Colors.green,
        Icons.people: Colors.green,
        Icons.favorite_border: Colors.green,
        Icons.directions_run: Colors.deepOrange,
        Icons.directions_car: Colors.blueGrey,
        Icons.hotel: Colors.deepPurpleAccent,
      };
      var tagIconList = [];
      var tagColorList = [];
    
      int _selectedIndex = 0;
    
      @override
      void initState() {
        super.initState();
        initData();
      }
    
      initData() {
        tagIconList = tagMap.keys.toList();
        tagColorList = tagMap.values.toList();
      }
    
      List<String> tagNames = [
        'Work',
        'Relax',
        'Eating',
        'Family',
        'Friends',
        'Relationship',
        'Sport',
        'Transport',
        'Sleep'
      ];
    
      _addTagOption() async {
        setState(() {
          tagMap.putIfAbsent(Icons.laptop, () => Colors.deepOrange);
          tagNames.add('Challenge');
          initData();
        });
        Navigator.of(context).pop();
        _showDialog();
      }
    
      void _showDialog() {
        showDialog(
            context: context,
            builder: (BuildContext context) {
              return SimpleDialog(
                  shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10.0))),
                  children: <Widget>[
                    Container(
                        width: double.maxFinite,
                        child: ListView.builder(
                            itemCount: tagMap.length,
                            shrinkWrap: true,
                            itemBuilder: (BuildContext context, int itemCount) {
                              return SimpleDialogOption(
                                  onPressed: () {
                                    setState(() {
                                      _selectedIndex = itemCount;
                                    });
                                    Navigator.of(context).pop();
                                  },
                                  child: Row(
                                    children: <Widget>[
                                      Icon(
                                        tagIconList[itemCount],
                                        color: tagColorList[itemCount],
                                      ),
                                      Padding(padding: EdgeInsets.only(left: 25), child: Text(tagNames[itemCount]))
                                    ],
                                  ));
                            })),
                    SimpleDialogOption(
                      onPressed: _addTagOption,
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: <Widget>[
                          Icon(
                            Icons.add,
                            size: 25,
                            color: Color(0x8A000000),
                          ),
                          Padding(
                              padding: EdgeInsets.only(left: 5),
                              child: Text(
                                'ADD NEW',
                                style: TextStyle(color: Color(0x8A000000)),
                              ))
                        ],
                      ),
                    )
                  ]);
            });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(
              "TAGS",
              style: TextStyle(color: Colors.white),
            ),
          ),
          body: Column(
            children: <Widget>[
              Text("Selected Tag"),
              SizedBox(
                height: 20,
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Icon(
                    tagIconList[_selectedIndex],
                    color: tagColorList[_selectedIndex],
                  ),
                  Padding(padding: EdgeInsets.only(left: 25), child: Text(tagNames[_selectedIndex]))
                ],
              ),
              SizedBox(
                height: 20,
              ),
              RaisedButton(
                onPressed: _showDialog,
                child: Text("Select TAG"),
              )
            ],
          ),
        );
      }
    }
    

    Hope it helps :)