Comment ajouter un ListView à une colonne dans Flutter?

125

J'essaie de créer une page de connexion simple pour mon application Flutter. J'ai construit avec succès les boutons TextFields et Login / Signin. Je veux ajouter un ListView horizontal. Lorsque j'exécute le code, mes éléments disparaissent, si je le fais sans ListView, ça va à nouveau. Comment puis-je faire cela correctement?

return new MaterialApp(
        home: new Scaffold(
          appBar: new AppBar(
            title: new Text("Login / Signup"),
          ),
          body: new Container(
            child: new Center(
              child: new Column(
              mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  new TextField(
                    decoration: new InputDecoration(
                      hintText: "E M A I L    A D D R E S S"
                    ),
                  ),
                  new Padding(padding: new EdgeInsets.all(15.00)),
                  new TextField(obscureText: true,
                    decoration: new InputDecoration(
                      hintText: "P A S S W O R D"
                    ),
                    ),
                  new Padding(padding: new EdgeInsets.all(15.00)),
                  new TextField(decoration: new InputDecoration(
                    hintText: "U S E R N A M E"
                  ),),
                  new RaisedButton(onPressed: null,
                  child:  new Text("SIGNUP"),),
                  new Padding(padding: new EdgeInsets.all(15.00)),
                  new RaisedButton(onPressed: null,
                  child: new Text("LOGIN"),),
                  new Padding(padding: new EdgeInsets.all(15.00)),
                  new ListView(scrollDirection: Axis.horizontal,
                  children: <Widget>[
                    new RaisedButton(onPressed: null,
                    child: new Text("Facebook"),),
                    new Padding(padding: new EdgeInsets.all(5.00)),
                    new RaisedButton(onPressed: null,
                    child: new Text("Google"),)
                  ],)

                ],
              ),
            ),
            margin: new EdgeInsets.all(15.00),
          ),
        ),
      );
Charles Jr
la source

Réponses:

75

Vous pouvez vérifier la sortie de la console. Il imprime l'erreur:

L'assertion suivante a été lancée pendant performResize (): La fenêtre horizontale a reçu une hauteur illimitée. Les fenêtres se développent dans l'axe transversal pour remplir leur conteneur et contraignent leurs enfants à correspondre à leur étendue dans l'axe transversal. Dans ce cas, une fenêtre horizontale a reçu une quantité illimitée d'espace vertical dans laquelle se développer.

Vous devez ajouter une contrainte de hauteur à votre liste horizontale. Par exemple, envelopper dans un conteneur avec hauteur:

Container(
  height: 44.0,
  child: ListView(
    scrollDirection: Axis.horizontal,
    children: <Widget>[
      RaisedButton(
        onPressed: null,
        child: Text("Facebook"),
      ),
      Padding(padding: EdgeInsets.all(5.00)),
      RaisedButton(
        onPressed: null,
        child: Text("Google"),
      )
    ],
  ),
)
Allemand Saprykin
la source
6
les deux réponses suivantes donnent deux autres solutions et expliquent ce qui se passe.
pashute
299

J'ai aussi ce problème. Ma solution est d'utiliser un Expandedwidget pour agrandir l'espace restant.

new Column(
  children: <Widget>[
    new Expanded(
      child: horizontalList,
    )
  ],
);
up2up
la source
2
C'est une excellente solution car elle permet des hauteurs / largeurs de taille variable du ListView, comme lorsque vous voulez qu'il occupe juste l'espace restant. Il vous permet de tenir compte des différentes tailles d'écran lorsqu'il est trop difficile de connaître la hauteur / largeur exacte.
Daniel Allen
1
Cela devrait être la réponse acceptée. Cette solution permet à ListView de prendre le reste de l'écran sans avoir à traiter la requête multimédia.
Terence Ponce
Je suis trop nouveau sur Flutter pour savoir pourquoi cela fonctionne, mais je suis content que ce soit le cas. Je vous remercie. Les messages d'erreur de Flutter n'étaient pas très utiles pour expliquer la cause première de ce problème à un non-expert.
devdanke le
Merci, votre réponse me fait gagner du temps.
Licat Julius
126

Raison de l'erreur:

Column se développe jusqu'à la taille maximale dans la direction de l'axe principal (axe vertical), tout comme le ListView .

Solutions

Vous devez donc contraindre la hauteur du fichier ListView. Il existe de nombreuses façons de le faire, vous pouvez choisir celle qui correspond le mieux à vos besoins.


  1. Si vous voulez permettre ListViewde prendre tout l' espace restant à l' intérieur Columnutilisation Expanded.

    Column(
      children: <Widget>[
        Expanded(
          child: ListView(...),
        )
      ],
    )

  1. Si vous souhaitez limiter votre ListViewà certains height, vous pouvez utiliser SizedBox.

    Column(
      children: <Widget>[
        SizedBox(
          height: 200, // constrain height
          child: ListView(),
        )
      ],
    )

  1. Si votre ListViewest petit, vous pouvez essayer une shrinkWrappropriété dessus.

    Column(
      children: <Widget>[
        ListView(
          shrinkWrap: true, // use it
        )
      ],
    )
CopsOnRoad
la source
Ma taille ne doit pas être fixée et les autres réponses n'ont pas fonctionné pour moi = /
Daniel Vilela
1
@DanielVilela L'option 1 devrait fonctionner pour vous. Sinon, postez-la sous forme de question et si je suis disponible, je peux y répondre.
CopsOnRoad
1
Je l'ai fait fonctionner! Merci. J'ai dû mettre un Expanded () à certains endroits stratégiques.
Daniel Vilela
Merci, je n'ai pas pensé à Expanded.
Gilvan André
Merci pour shrinkWrap: true dans ListView ()
Rana Hyder
18

J'ai SingleChildScrollViewcomme parent, et un Columnwidget , puis un widget d'affichage de liste comme dernier enfant.

L'ajout de ces propriétés dans la vue Liste a fonctionné pour moi.

  physics: NeverScrollableScrollPhysics(),
  shrinkWrap: true,
  scrollDirection: Axis.vertical,
Développer
la source
14

Expanded Widget augmente sa taille autant qu'il le peut avec l'espace disponible Puisque ListView a essentiellement une hauteur infinie, cela provoquera une erreur.

 Column(
  children: <Widget>[
    Flexible(
      child: ListView(...),
    )
  ],
)

Ici, nous devrions utiliser le widget Flexible car il ne prendra que l'espace requis car Expanded prend le plein écran même s'il n'y a pas assez de widgets pour un rendu en plein écran.

jitsm555
la source
10

En fait, lorsque vous lisez des documents, ListView doit être à l'intérieur du widget étendu pour qu'il puisse fonctionner.

  Widget build(BuildContext context) {
return Scaffold(
    body: Column(
  children: <Widget>[
    Align(
      child: PayableWidget(),
    ),
    Expanded(
      child: _myListView(context),
    )
  ],
));

}

Richie
la source
7

Comme cela a été mentionné par d'autres ci-dessus, Wrap listview avec Expanded est la solution.

Mais lorsque vous traitez avec des colonnes imbriquées, vous devrez également limiter votre ListView à une certaine hauteur (ce problème est souvent rencontré).

Si quelqu'un a une autre solution, veuillez la mentionner en commentaire ou ajouter une réponse.

Exemple

  SingleChildScrollView(
   child: Column(
     children: <Widget>[
       Image(image: ),//<< any widgets added
       SizedBox(),
       Column(
         children: <Widget>[
           Text('header'),  //<< any widgets added
            Expanded(child: 
            ListView.builder(
              //here your code
               scrollDirection: Axis.horizontal,
        itemCount: items.length,
        itemBuilder: (BuildContext context, int index) {
            return Container();
                   } 
         )
        ),
        Divider(),//<< any widgets added
         ],
       ),

     ],
   ), 
  );
UN..D
la source
dans les colonnes imbriquées, n'utilisez pas les propriétés développées, utilisez simplement shrikWrap: true, physique: NeverScrolPhysics () propriétés dans listView
Mohamed Kamel
5

Vous pouvez utiliser Flexet des Flexiblewidgets. par exemple:

Flex(
direction: Axis.vertical,
children: <Widget>[
    ... other widgets ...
    Flexible(
        flex: 1,
        child: ListView.builder(
        itemCount: ...,
        itemBuilder: (context, index) {
            ...
        },
        ),
    ),
],

);

Moein Fazeli
la source
0
return new MaterialApp(
    home: new Scaffold(
      appBar: new AppBar(
        title: new Text("Login / Signup"),
      ),
      body: new Container(
        child: new Center(
          child: ListView(
          //mainAxisAlignment: MainAxisAlignment.center,
          scrollDirection: Axis.vertical,
            children: <Widget>[
              new TextField(
                decoration: new InputDecoration(
                  hintText: "E M A I L    A D D R E S S"
                ),
              ),
              new Padding(padding: new EdgeInsets.all(15.00)),
              new TextField(obscureText: true,
                decoration: new InputDecoration(
                  hintText: "P A S S W O R D"
                ),
                ),
              new Padding(padding: new EdgeInsets.all(15.00)),
              new TextField(decoration: new InputDecoration(
                hintText: "U S E R N A M E"
              ),),
              new RaisedButton(onPressed: null,
              child:  new Text("SIGNUP"),),
              new Padding(padding: new EdgeInsets.all(15.00)),
              new RaisedButton(onPressed: null,
              child: new Text("LOGIN"),),
              new Padding(padding: new EdgeInsets.all(15.00)),
              new ListView(scrollDirection: Axis.horizontal,
              children: <Widget>[
                new RaisedButton(onPressed: null,
                child: new Text("Facebook"),),
                new Padding(padding: new EdgeInsets.all(5.00)),
                new RaisedButton(onPressed: null,
                child: new Text("Google"),)
              ],)

            ],
          ),
        ),
        margin: new EdgeInsets.all(15.00),
      ),
    ),
  );
VenkatSainathReddy
la source
-1

Essayez d'utiliser Slivers:

Container(
    child: CustomScrollView(
      slivers: <Widget>[
        SliverList(
          delegate: SliverChildListDelegate(
            [
              HeaderWidget("Header 1"),
              HeaderWidget("Header 2"),
              HeaderWidget("Header 3"),
              HeaderWidget("Header 4"),
            ],
          ),
        ),
        SliverList(
          delegate: SliverChildListDelegate(
            [
              BodyWidget(Colors.blue),
              BodyWidget(Colors.red),
              BodyWidget(Colors.green),
              BodyWidget(Colors.orange),
              BodyWidget(Colors.blue),
              BodyWidget(Colors.red),
            ],
          ),
        ),
        SliverGrid(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
          delegate: SliverChildListDelegate(
            [
              BodyWidget(Colors.blue),
              BodyWidget(Colors.green),
              BodyWidget(Colors.yellow),
              BodyWidget(Colors.orange),
              BodyWidget(Colors.blue),
              BodyWidget(Colors.red),
            ],
          ),
        ),
      ],
    ),
  ),
)
Morteza Rastgoo
la source