Как добавить ListView в столбец во Flutter?

128

Я пытаюсь создать простую страницу входа в свое приложение Flutter. Я успешно создал кнопки TextFields и Login / Signin. Я хочу добавить горизонтальный ListView. Когда я запускаю код, мои элементы исчезают, если я делаю это без ListView, все снова в порядке. Как мне это сделать правильно?

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),
          ),
        ),
      );
Чарльз младший
источник

Ответы:

75

Вы можете проверить вывод консоли. Он печатает ошибку:

Во время performResize () было выдано следующее утверждение: Горизонтальному окну просмотра была присвоена неограниченная высота. Видовые экраны расширяются по поперечной оси, заполняя свой контейнер, и ограничивают своих дочерних элементов, чтобы они соответствовали их протяженности по поперечной оси. В этом случае горизонтальному окну просмотра было предоставлено неограниченное количество вертикального пространства для расширения.

Вам нужно добавить ограничение высоты в свой горизонтальный список. Например, упаковка в контейнер с высотой:

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"),
      )
    ],
  ),
)
Герман Сапрыкин
источник
7
следующие два ответа дают еще два решения и объясняют, что происходит.
пашуте 02
300

У меня тоже есть эта проблема. Мое решение - использовать Expandedвиджет для увеличения оставшегося места.

new Column(
  children: <Widget>[
    new Expanded(
      child: horizontalList,
    )
  ],
);
up2up
источник
2
Это отличное решение, потому что оно позволяет изменять высоту / ширину ListView, например, когда вы хотите, чтобы он просто занимал оставшееся пространство. Это позволяет вам учитывать различные размеры экрана, когда слишком сложно определить точную высоту / ширину.
Дэниел Аллен
1
Это должен быть принятый ответ. Это решение позволяет ListView занять остальную часть экрана без необходимости обрабатывать медиа-запросы.
Теренс Понсе
Я слишком новичок во Flutter, чтобы знать, почему это работает, но я рад, что это так. Спасибо. Сообщения об ошибках Flutter не очень помогли неспециалисту объяснить основную причину этой проблемы.
devdanke
Спасибо, ваш ответ сэкономит мне время.
Licat Julius,
126

Причина ошибки:

Columnрасширяется до максимального размера в направлении главной оси (вертикальной оси), как и размер ListView.

Решения

Итак, вам нужно ограничить высоту ListView. Есть много способов сделать это, и вы можете выбрать наиболее подходящий для вас.


  1. Если вы хотите позволить ListViewзанять все оставшееся пространство внутри, Columnиспользуйте Expanded.

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

  1. Если вы хотите ограничить свой ListViewвыбор height, вы можете использовать SizedBox.

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

  1. Если ваш ListViewмаленький, вы можете примерить shrinkWrapна нем недвижимость.

    Column(
      children: <Widget>[
        ListView(
          shrinkWrap: true, // use it
        )
      ],
    )
CopsOnRoad
источник
Мой рост не должен быть фиксированным, и другие ответы не
Даниэль Вилела
1
@DanielVilela Вариант 1 должен работать на вас. Если нет, опубликуйте его как вопрос, и если я буду доступен, я могу на него ответить.
CopsOnRoad 05
1
Я заставил его работать! Спасибо. Мне пришлось разместить Expanded () в некоторых стратегических местах.
Даниэль Вилела
Спасибо, про Expanded не подумал.
Гилван Андре
Спасибо за shrinkWrap: true в ListView ()
Рана Хайдер
18

У меня SingleChildScrollViewв качестве родителя и один Columnвиджет, а затем виджет просмотра списка в качестве последнего дочернего элемента.

Добавление этих свойств в список сработало для меня.

  physics: NeverScrollableScrollPhysics(),
  shrinkWrap: true,
  scrollDirection: Axis.vertical,
Developine
источник
16

Expanded Widget увеличивает свой размер настолько, насколько это возможно, с доступным пространством. Поскольку ListView по существу имеет бесконечную высоту, это вызовет ошибку.

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

Здесь мы должны использовать гибкий виджет, так как он будет занимать только необходимое пространство, так как расширенный занимает весь экран, даже если виджетов недостаточно для рендеринга в полноэкранном режиме.

jitsm555
источник
10

На самом деле, когда вы читаете документы, ListView должен находиться внутри Expanded Widget, чтобы он мог работать.

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

}

Ричи
источник
7

Как уже упоминалось выше, обернуть список с расширенным решением - это решение.

Но когда вы имеете дело с вложенными столбцами, вам также необходимо ограничить ListView определенной высотой (часто сталкивался с этой проблемой).

Если у кого-то есть другое решение, укажите в комментарии или добавьте ответ.

пример

  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
источник
во вложенных столбцах не используйте расширенный, просто используйте свойства shrikWrap: true, Physics: NeverScrolPhysics () в listView
Мохамед Камель
5

Можно использовать Flexи Flexibleвиджеты. например:

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

Попробуйте использовать 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),
            ],
          ),
        ),
      ],
    ),
  ),
)
Мортеза Растгоо
источник