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),
          ),
        ),
      );
Charles Jr
źródło

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"),
      )
    ],
  ),
)
Niemiecki Saprykin
źródło
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,
    )
  ],
);
up2up
źródło
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
        )
      ],
    )
CopsOnRoad
źródło
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,
Rozwijaj
źródło
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.

jitsm555
źródło
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),
    )
  ],
));

}

Richie
źródło
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
         ],
       ),

     ],
   ), 
  );
UN..D
źródło
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) {
            ...
        },
        ),
    ),
],

);

Moein Fazeli
źródło
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
źródło
-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),
            ],
          ),
        ),
      ],
    ),
  ),
)
Morteza Rastgoo
źródło