Iterating through a list to render multiple widgets in Flutter?

FlutterLoopsDart

Flutter Problem Overview


I have a list of strings defined like this:

var list = ["one", "two", "three", "four"]; 

I want to render the values on the screen side by side using text widgets. I have attempted to use the following code to attempt this:

for (var name in list) {
   return new Text(name);
}

However, when I run this code, the for loop only runs once and there is only one text widget that gets rendered that says one (the first item in the list). Additionally, when I add a log message inside my for loop, it gets triggered once as well. Why isn't my for loop looping based on the length of the list? It seems to run only once and then quit.

Flutter Solutions


Solution 1 - Flutter

Basically when you hit 'return' on a function the function will stop and will not continue your iteration, so what you need to do is put it all on a list and then add it as a children of a widget

you can do something like this:

  Widget getTextWidgets(List<String> strings)
  {
    List<Widget> list = new List<Widget>();
    for(var i = 0; i < strings.length; i++){
        list.add(new Text(strings[i]));
    }
    return new Row(children: list);
  }

or even better, you can use .map() operator and do something like this:

  Widget getTextWidgets(List<String> strings)
  {
    return new Row(children: strings.map((item) => new Text(item)).toList());
  }

Solution 2 - Flutter

It is now possible to achieve that in Flutter 1.5 and Dart 2.3 by using a for element in your collection.

var list = ["one", "two", "three", "four"]; 

child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
             for(var item in list ) Text(item)
          ],
        ),    

This will display four Text widgets containing the items in the list.
NB. No braces around the for loop and no return keyword.

Solution 3 - Flutter

The Dart language has aspects of functional programming, so what you want can be written concisely as:

List<String> list = ['one', 'two', 'three', 'four'];
List<Widget> widgets = list.map((name) => new Text(name)).toList();

Read this as "take each name in list and map it to a Text and form them back into a List".

Solution 4 - Flutter

For googler, I wrote a simple Stateless Widget containing 3 method mentioned in this SO. Hope this make it easier to understand.

import 'package:flutter/material.dart';

class ListAndFP extends StatelessWidget {
  final List<String> items = ['apple', 'banana', 'orange', 'lemon'];

  //  for in (require dart 2.2.2 SDK or later)
  Widget method1() {
    return Column(
      children: <Widget>[
        Text('You can put other Widgets here'),
        for (var item in items) Text(item),
      ],
    );
  }

  // map() + toList() + Spread Property
  Widget method2() {
    return Column(
      children: <Widget>[
        Text('You can put other Widgets here'),
        ...items.map((item) => Text(item)).toList(),
      ],
    );
  }

  // map() + toList()
  Widget method3() {
    return Column(
      // Text('You CANNOT put other Widgets here'),
      children: items.map((item) => Text(item)).toList(),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: method1(),
    );
  }
}

Solution 5 - Flutter

All you need to do is put it in a list and then add it as the children of the widget.

you can do something like this:

Widget listOfWidgets(List<String> item) {
  List<Widget> list = List<Widget>();
  for (var i = 0; i < item.length; i++) {
    list.add(Container(
        child: FittedBox(
          fit: BoxFit.fitWidth,
          child: Text(
            item[i],
          ),
        )));
  }
  return Wrap(
      spacing: 5.0, // gap between adjacent chips
      runSpacing: 2.0, // gap between lines
      children: list);
}

After that call like this

child: Row(children: <Widget>[
   listOfWidgets(itemList),
])

enter image description here

Solution 6 - Flutter

To loop through a for-loop with multiple widgets in children,

children: [
  for(int i = 0; i < item.length; i++) ...[    Widget1,    Widget2,    ...  ],
],

Solution 7 - Flutter

The simplest way is to map your list inside a Row or a Column widget :

var list = ["one", "two", "three", "four"]; 

Widget build(BuildContext context) {
    return Row(children: List.from(list.map((name) => Text(name))));
}

Solution 8 - Flutter

You can use ListView to render a list of items. But if you don't want to use ListView, you can create a method which returns a list of Widgets (Texts in your case) like below:

var list = ["one", "two", "three", "four"];

    @override
    Widget build(BuildContext context) {
      return new MaterialApp(
          home: new Scaffold(
        appBar: new AppBar(
          title: new Text('List Test'),
        ),
        body: new Center(
          child: new Column( // Or Row or whatever :)
            children: createChildrenTexts(),
          ),
        ),
      ));
    }

     List<Text> createChildrenTexts() {
    /// Method 1
//    List<Text> childrenTexts = List<Text>();
//    for (String name in list) {
//      childrenTexts.add(new Text(name, style: new TextStyle(color: Colors.red),));
//    }
//    return childrenTexts;

    /// Method 2
    return list.map((text) => Text(text, style: TextStyle(color: Colors.blue),)).toList();
  }

Solution 9 - Flutter

You can make use of ListView.Builder() if you are receiving response from a http request that as an array

List items = data;

Container(
  child: ListView.builder(
    shrinkWrap: true,
    itemCount: items.length,
    itemBuilder: (BuildContext context, int index){
      return Container(
        child: Text(
          items[index]['property']
        ),
      );
    },
  ),
);

Where data is content returned from a http request using post or get item is the array 'property' is one of the property of each item in the array assuming your are receiving back a list of objects

Solution 10 - Flutter

An easier approach may be to use expand:

For example

var paragraphs = ['Para1','Para2','Para3'];

Somewhere in your widget tree you can do this:

...paragraphs.expand((value) => [
SizedBox(
      height: 10.0,
    ),
    Text(
      value,
      // Add some styling if necessary
    ),
    SizedBox(
      height: 20.0,
    ),
  ]),

Here expand returns an iterable of widgets which is then spread using the Spread Operator(...).

Solution 11 - Flutter

when you return some thing, the code exits out of the loop with what ever you are returning.so, in your code, in the first iteration, name is "one". so, as soon as it reaches return new Text(name), code exits the loop with return new Text("one"). so, try to print it or use asynchronous returns.

Solution 12 - Flutter

Below works for me using the collection package :

https://pub.dev/packages/collection

children: <Widget>[
                ...languages.mapIndex((idx, item) {
                  return InkWell(
                      child: CustomCheckbox(Skill(item, _languageSelections[idx])),
                      onTap: () {
                        setState(() {
                          _languageSelections[idx] = !_languageSelections[idx];
                        });
                      });
                })
              ],

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrakeshdasView Question on Stackoverflow
Solution 1 - FlutterRizky AndriawanView Answer on Stackoverflow
Solution 2 - FlutternonybrightoView Answer on Stackoverflow
Solution 3 - FlutterRichard HeapView Answer on Stackoverflow
Solution 4 - Flutteruser2875289View Answer on Stackoverflow
Solution 5 - FlutterParesh MangukiyaView Answer on Stackoverflow
Solution 6 - FlutterltkView Answer on Stackoverflow
Solution 7 - FlutterjvlamyView Answer on Stackoverflow
Solution 8 - FlutterPhuc TranView Answer on Stackoverflow
Solution 9 - FlutterLightwaxxView Answer on Stackoverflow
Solution 10 - FluttersjsamView Answer on Stackoverflow
Solution 11 - FlutterInAFlashView Answer on Stackoverflow
Solution 12 - Fluttergandharv gargView Answer on Stackoverflow