Jak dodać ListView do kolumny w Flutter?


125

Próbuję stworzyć prostą stronę logowania do mojej aplikacji Flutter. Udało mi się zbudować przyciski TextField i Login / Signin. Chcę dodać poziomy ListView. Kiedy uruchamiam kod, moje elementy znikają, jeśli zrobię to bez ListView, znowu jest dobrze. Jak mogę to zrobić poprawnie?

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

Odpowiedzi:


75

Możesz sprawdzić wyjście konsoli. Wyświetla błąd:

Następujące stwierdzenie zostało zgłoszone podczas performResize (): Rzutnia pozioma otrzymała nieograniczoną wysokość. Rzutnie rozszerzają się na osi poprzecznej, wypełniając swój pojemnik i ograniczając swoje elementy podrzędne do dopasowania ich zasięgu na osi poprzecznej. W tym przypadku pozioma rzutnia otrzymała nieograniczoną ilość pionowej przestrzeni na rozszerzenie.

Musisz dodać ograniczenie wysokości do listy poziomej. Np. Zawinąć w Pojemnik o wysokości:

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
następne dwie odpowiedzi dają kolejne dwa rozwiązania i wyjaśniają, co się dzieje.
pashute

299

Ja też mam ten problem. Moim rozwiązaniem jest użycie Expandedwidżetu, aby powiększyć pozostałą przestrzeń.

new Column(
  children: <Widget>[
    new Expanded(
      child: horizontalList,
    )
  ],
);

2
Jest to świetne rozwiązanie, ponieważ pozwala na zmienne wysokości / szerokości ListView, na przykład gdy chcesz, aby zajmował pozostałą przestrzeń. Pozwala uwzględnić różne rozmiary ekranu, gdy określenie dokładnej wysokości / szerokości jest zbyt trudne.
Daniel Allen

1
To powinna być akceptowana odpowiedź. To rozwiązanie pozwala ListView zająć resztę ekranu bez konieczności zajmowania się zapytaniami o media.
Terence Ponce

Jestem zbyt nowy dla Fluttera, by wiedzieć, dlaczego to działa, ale cieszę się, że tak. Dziękuję Ci. Komunikaty o błędach Fluttera nie były zbyt pomocne w wyjaśnieniu podstawowej przyczyny tego problemu osobie niebędącej ekspertem.
devdanke

Dzięki, twoja odpowiedź oszczędza mój czas.
Licat Julius

126

Przyczyna błędu:

Column rozwija się do maksymalnego rozmiaru w kierunku osi głównej (oś pionowa), podobnie jak ListView .

Rozwiązania

Musisz więc ograniczyć wysokość ListView. Jest na to wiele sposobów, możesz wybrać ten, który najlepiej odpowiada Twoim potrzebom.


  1. Jeśli chcesz pozwolić ListViewzająć całą pozostałą przestrzeń w środku, Columnużyj Expanded.

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

  1. Jeśli chcesz ograniczyć się ListViewdo pewności height, możesz użyć SizedBox.

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

  1. Jeśli twój ListViewjest mały, możesz spróbować shrinkWrapna nim nieruchomości.

    Column(
      children: <Widget>[
        ListView(
          shrinkWrap: true, // use it
        )
      ],
    )

Mój wzrost nie powinien być ustalany, a inne odpowiedzi nie działają dla mnie = /
Daniel Vilela

1
@DanielVilela Opcja 1 powinna działać dla Ciebie. Jeśli nie, opublikuj to jako pytanie, a jeśli będę dostępny, mogę na nie odpowiedzieć.
CopsOnRoad

1
Mam to do pracy! Dzięki. Musiałem umieścić Expanded () w niektórych strategicznych miejscach.
Daniel Vilela

Dzięki, nie myślałem o rozszerzeniu.
Gilvan André

Dzięki za shrinkWrap: true w ListView ()
Rana Hyder

18

Mam SingleChildScrollViewjako rodzica i jednegoColumn widżet, a następnie widżet widoku listy jako ostatnie dziecko.

Dodanie tych właściwości w widoku listy zadziałało dla mnie.

  physics: NeverScrollableScrollPhysics(),
  shrinkWrap: true,
  scrollDirection: Axis.vertical,

14

Expanded Widget zwiększa swój rozmiar tak bardzo, jak to tylko możliwe dzięki dostępnemu miejscu. Ponieważ ListView ma zasadniczo nieskończoną wysokość, spowoduje błąd.

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

Tutaj powinniśmy użyć elastycznego widżetu, ponieważ zajmie tylko wymaganą przestrzeń, ponieważ rozwinięty zajmuje pełny ekran, nawet jeśli nie ma wystarczającej liczby widżetów do renderowania na pełnym ekranie.


10

Właściwie, kiedy czytasz dokumenty, ListView powinien znajdować się wewnątrz Expanded Widget, aby mógł działać.

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

}


7

Jak wspomnieli inni powyżej, rozwiązaniem jest Wrap listview with Expanded.

Ale kiedy zajmujesz się zagnieżdżonymi kolumnami, będziesz musiał również ograniczyć ListView do określonej wysokości (często napotykasz ten problem).

Jeśli ktoś ma inne rozwiązanie, proszę o wzmiankę w komentarzu lub dodanie odpowiedzi.

Przykład

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

     ],
   ), 
  );

w kolumnach zagnieżdżonych nie używaj rozwiniętego, tylko użyj shrikWrap: true, właściwości physics: NeverScrolPhysics () w listView
Mohamed Kamel

5

Możesz używać Flexi Flexiblewidżetów. na przykład:

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

Spróbuj użyć 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),
            ],
          ),
        ),
      ],
    ),
  ),
)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.