Итерирование через список для отображения нескольких виджетов в 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")
. поэтому попробуйте распечатать его или использовать асинхронные возвращения.