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

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"),
      )
    ],
  ),
)

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,
    )
  ],
);

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
        )
      ],
    )

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,

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.


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),
    )
  ],
));

}


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
         ],
       ),

     ],
   ), 
  );

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) {
            ...
        },
        ),
    ),
],

);


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

-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),
            ],
          ),
        ),
      ],
    ),
  ),
)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.