Итерирование через список для отображения нескольких виджетов в Flutter?

У меня есть список строк, определенных следующим образом:

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

Я хочу отображать значения на экране бок о бок, используя текстовые виджеты. Для этого я попытался использовать следующий код:

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

Однако, когда я запускаю этот код, цикл for работает только один раз, и есть только один текстовый виджет, который получает визуализацию, который говорит one (первый элемент в списке). Кроме того, когда я добавляю сообщение журнала внутри цикла for, он запускается одновременно. Почему мой цикл цикла for не зависит от длины списка? Кажется, он запускается только один раз, а затем уходит.

Ответы

Ответ 1

По сути, когда вы нажимаете "return" для функции, функция останавливается и не будет продолжать вашу итерацию, поэтому вам нужно поместить все это в список, а затем добавить в качестве дочерних элементов виджета.

Вы можете сделать что-то вроде этого:

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

или даже лучше, вы можете использовать оператор .map() и сделать что-то вроде этого:

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

Ответ 2

Теперь можно достичь этого во Flutter 1.5 и Dart 2.3, используя элемент for в вашей коллекции.

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

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

Это отобразит четыре текстовых виджета, содержащих элементы в списке.
NB. Никаких скобок вокруг цикла for и возвратного ключевого слова.

Ответ 3

Язык Dart имеет аспекты функционального программирования, поэтому то, что вы хотите, можно записать кратко, как:

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

Прочитайте это как "возьмите каждый name в list и сопоставьте его с Text и сгруппируйте их обратно в List".

Ответ 4

Вы можете использовать ListView для визуализации списка элементов. Но если вы не хотите использовать ListView, вы можете создать метод, который возвращает список виджетов (текстов в вашем случае), как показано ниже:

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();
  }

Ответ 5

Для googler я написал простой виджет без сохранения состояния, содержащий 3 метода, упомянутых в этом SO. Надеюсь, это облегчит понимание.

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

Ответ 6

когда вы возвращаете что-то, код выходит из цикла с тем, что когда-либо вы возвращаете. Так, в вашем коде на первой итерации имя "one". поэтому, как только он достигнет return new Text(name), код выходит из цикла с return new Text("one"). поэтому попробуйте распечатать его или использовать асинхронные возвращения.