Durch eine Liste iterieren, um mehrere Widgets in Flutter zu rendern?

76

Ich habe eine Liste von Zeichenfolgen wie folgt definiert:

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

Ich möchte die Werte auf dem Bildschirm mithilfe von Text-Widgets nebeneinander rendern. Ich habe versucht, den folgenden Code zu verwenden, um dies zu versuchen:

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

Wenn ich diesen Code ausführe, wird die for-Schleife jedoch nur einmal ausgeführt, und es wird nur ein Text-Widget gerendert, das besagt one(das erste Element in der Liste). Wenn ich eine Protokollnachricht in meine for-Schleife einfüge, wird diese außerdem einmal ausgelöst. Warum basiert meine for-Schleife nicht auf der Länge der Liste? Es scheint nur einmal zu laufen und dann zu beenden.

Rakeshdas
quelle
Warum verwenden Sie ListView nicht? Können Sie mehr Code darüber teilen, wie es Ihnen geht?
Phuc Tran

Antworten:

153

Wenn Sie bei einer Funktion auf "Zurück" klicken, wird die Funktion gestoppt und die Iteration nicht fortgesetzt. Sie müssen also alles auf eine Liste setzen und es dann als untergeordnete Elemente eines Widgets hinzufügen

Sie können so etwas tun:

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

oder noch besser, Sie können den Operator .map () verwenden und so etwas tun:

  Widget getTextWidgets(List<String> strings)
  {
    return new Row(children: strings.map((item) => new Text(item)).toList());
  }
Rizky Andriawan
quelle
1
Ist es auch möglich, ein Array von Widgets zurückzugeben?
KT Works
5
Seit Dart 2.3 können Sie die neue for-Schleifenmethode verwenden :return Row(children: [ for (var name in list) Text(name) ])
smac89
70

In Flutter 1.5 und Dart 2.3 ist dies jetzt möglich, indem Sie ein for- Element in Ihrer Sammlung verwenden.

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

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

Daraufhin werden vier Text-Widgets angezeigt, die die Elemente in der Liste enthalten.
NB. Keine geschweiften Klammern um die for-Schleife und kein return-Schlüsselwort.

nonybrighto
quelle
Hallo, ich bin vielleicht etwas spät dran, aber ich muss wissen, was ich tun soll, wenn mehrere Widgets in einer Schleife angezeigt werden sollen.
Faran Khan
Sie können sie in eine Spalte oder ein beliebiges Widget einschließen, das mehrere Widgets enthalten kann. Wenn ich deine Frage klar habe.
Nonybrighto
1
Wie kann ich mehr als ein Element in die Schleife einfügen? ZB for(var item in list ) { Text(item),Spacer() }würde nicht funktionieren.
A-letubby
2
Sie müssen die beiden Widgets in ein anderes Widget einschließen.
Nonybrighto
37

Die Dart-Sprache hat Aspekte der funktionalen Programmierung, sodass Sie genau das schreiben können, was Sie möchten:

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

Lesen Sie dies als "Nehmen Sie jedes nameauf listund ordnen Sie es einem zu Textund formen Sie es wieder zu einem List".

Richard Heap
quelle
2
Ich denke, dass dies eine bessere Antwort ist als die, die als gut markiert ist, da Sie dies tatsächlich direkt in der Build-Funktion verwenden können, ohne eine Funktion aufrufen zu müssen, die ein Widget zurückgibt
Jose Jet
Wie könnte ich den Index in diese .map bekommen?
Dani
1
@dani Sie können nicht mit Karte, aber Sie können mit der for-Schleife in Rizkys Antwort
Richard Heap
27

Für Googler habe ich ein einfaches Stateless Widget geschrieben, das drei in dieser SO erwähnte Methode enthält. Hoffe das macht es leichter zu verstehen.

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

Mit ListView können Sie eine Liste von Elementen rendern. Wenn Sie ListView jedoch nicht verwenden möchten, können Sie eine Methode erstellen, die eine Liste von Widgets (in Ihrem Fall Texte) wie folgt zurückgibt:

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();
  }
Phuc Tran
quelle
2
Liste <Text> ist kein Subtyp von Widget bro
Es funktioniert immer noch auf meiner Seite. Hast du einen Fehler bekommen? (Ich habe meinen Code aktualisiert, um 1 weitere Methode hinzuzufügen)
Phuc Tran
1

Alles, was Sie tun müssen, ist, es in eine Liste aufzunehmen und es dann als untergeordnete Elemente des Widgets hinzuzufügen.

Sie können so etwas tun:

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

Nach diesem Anruf so

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

Geben Sie hier die Bildbeschreibung ein

Paresh Mangukiya
quelle
0

Wenn Sie etwas zurückgeben, verlässt der Code die Schleife mit dem, was Sie zurückgeben. In Ihrem Code lautet der Name also in der ersten Iteration "one". Sobald es erreicht ist return new Text(name), verlässt der Code die Schleife mit return new Text("one"). Versuchen Sie also, es zu drucken, oder verwenden Sie asynchrone Rückgaben.

Im Nu
quelle