4

I have a list of objects each with an icon property as shown here:

List<Map<String, String>> _categories = [
    {
      'name': 'Sports',
      'icon': 'directions_run',
    },
    {
      'name': 'Politics',
      'icon': 'gavel',
    },
    {
      'name': 'Science',
      'icon': 'wb_sunny',
    },
];

I then have a widget that I am using inside of a ListView.builder() widget. Currently I am displaying a statically chosen icon to show with the text in my list. My question is how can I use the icon property in my objects to dynamically pick the icon that gets shown for each individual list item?

  Widget _buildCategoryCards(BuildContext context, int index) {
    return Container(
      padding: EdgeInsets.symmetric(vertical: 5.0),
      child: Card(
        child: Container(
          padding: EdgeInsets.all(15.0),
          child: Row(
            children: <Widget>[
              Icon(Icons.directions_run),
              SizedBox(width: 20.0),
              Text(_categories[index]['name']),
            ],
          ),
        ),
      ),
    );
  }
2
  • You can use index to decide which icon needs to be shown and then you can also use operator like index == 0 ? showThis: elseThis Commented Nov 12, 2018 at 2:47
  • How do I do that for each one though since it's a list? Commented Nov 12, 2018 at 11:39

2 Answers 2

15

Change your List to store an IconData instead of a String:

List<Map<String, IconData>> _categories = [
    {
      'name': 'Sports',
      'icon': Icons.directions_run,
    },
    {
      'name': 'Politics',
      'icon': Icons.gavel,
    },
    {
      'name': 'Science',
      'icon': Icons.wb_sunny,
    },
];

Then, call the IconData from your build method:

  Widget _buildCategoryCards(BuildContext context, int index) {
    return Container(
      padding: EdgeInsets.symmetric(vertical: 5.0),
      child: Card(
        child: Container(
          padding: EdgeInsets.all(15.0),
          child: Row(
            children: <Widget>[
              Icon(_categories[index]['icon']),
              SizedBox(width: 20.0),
              Text(_categories[index]['name']),
            ],
          ),
        ),
      ),
    );
  }

Note that this is not useful (even not effecient) to use a Map to do what you want. You should use a custom class:

Class Category {
  String name;
  IconData icon;

  Category(this.name, this.icon);
}

And then replace your List with this:

List<Category> _categories = [
    Category('Sports', Icons.directions_run),
    Category('Politics', Icons.gavel),
    Category('Science', Icons.wb_sunny),
];

finally in your Widget:

        children: <Widget>[
          Icon(_categories[index].icon),
          SizedBox(width: 20.0),
          Text(_categories[index].name),
        ],
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you this worked. Why isn't it useful / efficient to use Map in this situation?
Short answer: A Map is meant to manage a collection of key/value pair data. It is kinda the same as a List, but instead of accessing data through an index, you access it through a key (which can be of any type you want). So in your case, you have a List containing 3 collections of 1 item each. There is no need to have a collection if you have only 1 item in it.
0

Keep the icon identifier from Icons class in the list instead of storing the text. But if you want to create a mapping from icon label to icon identifier.

1 Comment

@UdeshUK Answers like this are best suited as comment.

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.