Як додати ListView до стовпця у Flutter?


125

Я намагаюся створити просту сторінку входу для свого додатка 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"),
      )
    ],
  ),
)

6
наступні дві відповіді дають ще два рішення та пояснюють, що відбувається.
пашуте

299

У мене теж є ця проблема. Моє рішення - використовувати Expandedвіджет, щоб розширити залишився простір.

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

2
Це відмінне рішення, оскільки воно дозволяє змінювати висоту / ширину ListView з різними розмірами, як, наприклад, коли ви хочете, щоб він просто зайняв залишок місця. Це дозволяє враховувати різні розміри екрану, коли занадто важко дізнатися точну висоту / ширину.
Даніель Аллен

1
Це має бути прийнятою відповіддю. Це рішення дозволяє ListView займати іншу частину екрана, не маючи справу з медіа-запитами.
Теренс Понс

Я занадто новачок у Flutter, щоб знати, чому це працює, але я радий, що це так. Дякую. Повідомлення про помилки Flutter були не дуже корисними для пояснення першопричини цієї проблеми для немедленного експерта.
devdanke

Дякую, ваша відповідь економить мій час.
Лікат Юлій

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

Мій зріст не слід фіксувати, а інші відповіді не спрацювали для мене = /
Daniel Vilela

1
@DanielVilela Варіант 1 повинен працювати для вас. Якщо ні, будь ласка, опублікуйте це як запитання, і якщо я є, я можу відповісти на нього.
CopsOnRoad

1
Я змусив його працювати! Дякую. Мені довелося поставити розширений () у деяких стратегічних місцях.
Даніель

Спасибі, я не думав про розширене.
Гільван Андре

Дякуємо за shrinkWrap: вірно в ListView ()
Рана Хайдер

18

Я SingleChildScrollViewяк батько, і один Columnвіджет, а потім віджет перегляду списку як остання дитина.

Додавання цих властивостей у перегляд списку працювало для мене.

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

14

Розширений віджет збільшує його розмір настільки, наскільки це можливо, з наявного місця, оскільки ListView по суті має нескінченну висоту, це призведе до помилки.

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

Тут ми повинні використовувати гнучкий віджет, оскільки він займе лише необхідний простір, оскільки розширений займає повний екран, навіть якщо не вистачає віджетів для візуалізації на весь екран.


10

Насправді, коли ви читаєте документи, ListView повинен знаходитись у розширеному віджеті, щоб він міг працювати.

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

}


7

Як вже згадувалося іншими вище, рішення Wrap listview з Expanded - це рішення.

Але коли ви маєте справу з вкладеними стовпцями, вам також потрібно буде обмежити ваш 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
         ],
       ),

     ],
   ), 
  );

у вкладених стовпцях не використовуйте розширені, просто використовуйте shrikWrap: true, physics: NeverScrolPhysics () властивості в listView
Mohamed Kamel

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),
            ],
          ),
        ),
      ],
    ),
  ),
)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.