Como adicionar um ListView a uma coluna no Flutter?

124

Estou tentando construir uma página de login simples para meu aplicativo Flutter. Criei com sucesso os botões TextFields e Login / Signin. Eu quero adicionar um ListView horizontal. Quando eu executo o código, meus elementos desaparecem, se eu fizer isso sem o ListView, tudo bem novamente. Como posso fazer isso corretamente?

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
fonte

Respostas:

73

Você pode verificar a saída do console. Ele imprime erro:

A seguinte asserção foi lançada durante performResize (): A janela de visualização horizontal recebeu altura ilimitada. As viewports se expandem no eixo cruzado para preencher seu contêiner e restringem seus filhos para que correspondam à sua extensão no eixo cruzado. Nesse caso, uma janela de visualização horizontal recebeu uma quantidade ilimitada de espaço vertical para expandir.

Você precisa adicionar restrição de altura à sua lista horizontal. Por exemplo, embrulhar no recipiente com altura:

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"),
      )
    ],
  ),
)
Saprykin Alemão
fonte
6
as próximas duas respostas fornecem outras duas soluções e explicam o que está acontecendo.
pashute
299

Eu também tenho esse problema. Minha solução é usar o Expandedwidget para expandir o espaço restante.

new Column(
  children: <Widget>[
    new Expanded(
      child: horizontalList,
    )
  ],
);
up2up
fonte
2
Esta é uma ótima solução porque permite alturas / larguras de tamanhos variáveis ​​do ListView, como quando você deseja que ele apenas ocupe o espaço restante. Ele permite que você considere os tamanhos de tela variados quando for muito difícil saber a altura / largura exata.
Daniel Allen
1
Esta deve ser a resposta aceita. Essa solução permite que o ListView ocupe o restante da tela sem ter que lidar com a consulta de mídia.
Terence Ponce
Sou muito novo no Flutter para saber por que isso funciona, mas estou feliz que funcione. Obrigado. As mensagens de erro do Flutter não foram muito úteis para explicar a causa raiz desse problema para um não especialista.
devdanke
Obrigado, sua resposta economiza meu tempo.
Licat Julius
125

Motivo do erro:

Columnse expande para o tamanho máximo na direção do eixo principal (eixo vertical), e o mesmo acontece com o ListView.

Soluções

Portanto, você precisa restringir a altura do ListView. Existem muitas maneiras de fazer isso, você pode escolher a que melhor se adapta às suas necessidades.


  1. Se você quiser permitir ListViewque ocupe todo o espaço restante dentro, Columnuse Expanded.

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

  1. Se quiser limitar o seu ListViewa certos height, você pode usar SizedBox.

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

  1. Se o seu ListViewfor pequeno, você pode tentar shrinkWrappropriedades nele.

    Column(
      children: <Widget>[
        ListView(
          shrinkWrap: true, // use it
        )
      ],
    )
CopsOnRoad
fonte
Minha altura não deveria ser corrigida e as outras respostas não funcionaram para mim = /
Daniel Vilela
1
@DanielVilela A opção 1 deve funcionar para você. Se não, por favor, poste como pergunta e se eu estiver disponível eu posso responder.
CopsOnRoad
1
Eu tenho que trabalhar! Obrigado. Tive que colocar um Expandido () em alguns lugares estratégicos.
Daniel Vilela
Obrigado, não pensei na Expanded.
Gilvan André
Obrigado por shrinkWrap: true in ListView ()
Rana Hyder
18

Eu tenho SingleChildScrollViewcomo pai, um Columnwidget e o widget de visualização de lista como último filho.

Adicionando essas propriedades na exibição de lista funcionou para mim.

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

O widget expandido aumenta seu tamanho o máximo que pode com o espaço disponível. Como ListView tem essencialmente uma altura infinita, ele causará um erro.

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

Aqui, devemos usar o widget Flexível, pois ele ocupará apenas o espaço necessário, já que o Expandido ocupa a tela inteira, mesmo que não haja widgets suficientes para renderizar na tela inteira.

jitsm555
fonte
10

Na verdade, quando você lê documentos, o ListView deve estar dentro do widget expandido para que possa funcionar.

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

}

Richie
fonte
7

Como foi mencionado por outros acima, Wrap listview with Expanded é a solução.

Mas quando você lida com colunas aninhadas, você também precisará limitar seu ListView a uma certa altura (enfrentou muito esse problema).

Se alguém tiver outra solução por favor, mencione em comentário ou adicione resposta.

Exemplo

  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
fonte
em colunas aninhadas, não use expandido, apenas use shrikWrap: true, physics: NeverScrolPhysics () properties in listView
Mohamed Kamel
5

Você pode usar Flexe Flexiblewidgets. por exemplo:

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

);

Moein Fazeli
fonte
-1

Tente usar 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
fonte