【问题标题】:How to add a ListView to a Column in Flutter?如何将 ListView 添加到 Flutter 中的列?
【发布时间】:2018-01-21 23:28:58
【问题描述】:

我正在尝试为我的 Flutter 应用构建一个简单的登录页面。我已经成功构建了 TextFields 和登录/登录按钮。我想添加一个水平 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),
          ),
        ),
      );

【问题讨论】:

    标签: flutter listview dart flutter-layout flutter-widget


    【解决方案1】:

    我也遇到了这个问题。我的解决方案是使用Expanded 小部件来扩展剩余空间。

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

    【讨论】:

    • 这是一个很好的解决方案,因为它允许 ListView 的可变大小的高度/宽度,例如当您希望它只占用剩余空间时。当很难知道确切的高度/宽度时,它允许您考虑不同的屏幕尺寸。
    • 这应该是公认的答案。该解决方案允许 ListView 占据屏幕的其余部分,而无需处理媒体查询。
    • 我对 Flutter 太陌生了,不知道为什么会这样,但我很高兴它确实如此。谢谢你。 Flutter 的错误消息对于非专家解释此问题的根本原因并不是很有帮助。
    • 简单,我在找什么。!会不会影响性能和渲染?
    • 谁能解释造成这个问题的原因以及为什么Expanded 修复它?
    【解决方案2】:

    错误原因:

    Column 在主轴方向(垂直轴)扩展到最大尺寸,ListView 也是如此。

    解决方案:

    因此,您需要限制ListView 的高度。有很多方法,你可以选择最适合你需要的。


    1. 如果您想让ListView 占用Column 内的所有剩余空间,请使用Expanded

      Column(
        children: <Widget>[
          Expanded( //        <-- Use 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, // Set this
          )
        ],
      )
      

    1. 如果您想让ListView 尽可能小,请使用FlexibleListView.shrinkWrap

      Column(
        children: <Widget>[
          Flexible( //        <-- Use Flexible 
            child: ListView(
              shrinkWrap: true, // and set this
            ),
          )
        ],
      )
      

    【讨论】:

    • 你的第三点是我强烈建议所有初学者注意的!
    【解决方案3】:

    您可以检查控制台输出。它打印错误:

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

    【讨论】:

    • 接下来的两个答案给出另外两个解决方案并解释发生了什么。
    • 有没有建议使用动态高度而不是固定列表视图的高度?
    【解决方案4】:

    Expanded Widget 会根据可用空间尽可能地增加其大小 由于 ListView 本质上具有无限的高度,因此会导致错误。

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

    在这里我们应该使用Flexible 小部件,因为即使没有足够的小部件在全屏上呈现,它也只会占用展开后全屏所需的空间。

    【讨论】:

    • 这是正确的解决方案!谢谢兄弟
    【解决方案5】:

    我有一个 SingleChildScrollView 作为父级,一个 Column Widget 和 List View Widget 作为最后一个子级。

    在列表视图中添加这些属性对我有用。

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

    【讨论】:

    • scrollDirection: Axis.vertical 是默认值,因此这不是解决方案的一部分。此外,这会禁用列表上的滚动。
    • 这必须是一个公认的答案!扩展和灵活的问题是flex,它占用了您为不同的灵活小部件计划的所有空间。 shrinkWrap 解决了这个问题,而 physics 禁用了溢出滚动效果。
    【解决方案6】:

    正如上面其他人所提到的,用 Expanded 包装列表视图是解决方案。

    但是当你处理嵌套的 Columns 时,你还需要将 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: NeverScrollPhysics() 属性在 listView
    • 使用 SingleChildScrollView 小部件包装溢出的列小部件(检查终端中的错误消息,您应该会看到导致错误的文件和行)。
    【解决方案7】:

    这是一个非常简单的方法。有不同的方法可以做到,比如你可以通过ExpandedSizedboxContainer获取,根据需要使用。

    1. 使用Expanded :扩展RowColumnFlex 的子级的小部件,以便子级填充可用空间。

      Expanded(
          child: ListView(scrollDirection: Axis.horizontal,
              children: <Widget>[
                OutlineButton(onPressed: null,
                    child: Text("Facebook")),
                Padding(padding: EdgeInsets.all(5.00)),
                OutlineButton(onPressed: null,
                    child: Text("Google")),
                Padding(padding: EdgeInsets.all(5.00)),
                OutlineButton(onPressed: null,
                    child: Text("Twitter"))
              ]),
        ),
      

    使用Expanded 小部件使RowColumnFlex 的子级扩展以填充沿主轴的可用空间(例如,水平用于行或垂直用于列)。

    1. 使用SizedBox :指定大小的盒子。

      SizedBox(
          height: 100,
          child: ListView(scrollDirection: Axis.horizontal,
              children: <Widget>[
                OutlineButton(
                    color: Colors.white,
                    onPressed: null,
                    child: Text("Amazon")
                ),
                Padding(padding: EdgeInsets.all(5.00)),
                OutlineButton(onPressed: null,
                    child: Text("Instagram")),
                Padding(padding: EdgeInsets.all(5.00)),
                OutlineButton(onPressed: null,
                    child: Text("SoundCloud"))
              ]),
       ),
      

    如果给定一个孩子,这个小部件会强制它的孩子有一个特定的宽度和/或高度(假设这个小部件的父级允许值)。

    1. 使用Container:一个方便的小部件,它结合了常见的绘画定位调整大小小部件。

       Container(
          height: 80.0,
          child: ListView(scrollDirection: Axis.horizontal,
              children: <Widget>[
                OutlineButton(onPressed: null,
                    child: Text("Shopify")),
                Padding(padding: EdgeInsets.all(5.00)),
                OutlineButton(onPressed: null,
                    child: Text("Yahoo")),
                Padding(padding: EdgeInsets.all(5.00)),
                OutlineButton(onPressed: null,
                    child: Text("LinkedIn"))
              ]),
        ),
      

    所有三个的输出都是这样的

    【讨论】:

    • 嘿@Paresh-Mangukiya 愚蠢的问题,你是如何组成整个屏幕的?换句话说,您是否有一个示例说明 Text 元素是如何置于每种不同方法之上的?
    • 在一个列中使用了全部三个组件
    【解决方案8】:

    实际上,当您阅读文档时,ListView 应该在 Expanded Widget 内,这样它才能工作。

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

    }

    【讨论】:

      【解决方案9】:

      您可以使用FlexFlexible 小部件。例如:

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

      );

      【讨论】:

      • 为什么选择 Flex?你可以解释吗?我认为 OP 正在询问如何在 Column 中添加 ListView。
      【解决方案10】:
        Column(
          children: <Widget>[
            Text('Leading text widget'),
            ListView(
              shrinkWrap: true,
              physics: NeverScrollableScrollPhysics(),
              children: <Widget>[
                ListTile(
                  leading: Icon(Icons.map),
                  title: Text('Map'),
                ),
                ListTile(
                  leading: Icon(Icons.photo_album),
                  title: Text('Album'),
                ),
                ListTile(
                  leading: Icon(Icons.phone),
                  title: Text('Phone'),
                ),
              ],
            ),
            Text('More widget'),
          ],
        );
      

      随便用

      shrinkWrap: true,
      
      physics: NeverScrollableScrollPhysics(),
      

      listView 中的属性

      【讨论】:

      • 介意解释一下你的答案吗?
      • 问题是how to add listview in a column 我认为这解决了我的问题。想知道为什么这没有被投票。也许我从那里的流行答案中遗漏了一些东西?
      • 我需要将Column 包装成child of SingleChildScrollView
      【解决方案11】:

      [解决方案预览] - [列表项可滚动但标题固定]

      我有一个非常小而直接的答案,请参阅将 listview 放在列中会强制列无限扩展,这基本上是一个错误。

      现在,如果您像其他人建议的那样将 physics: NeverScrollableScrollPhysics(), 放在 listview 中,那么如果您禁用在其中滚动,那么拥有 listview 的意义何在..

      有一个简单的解决方法,坦率地说,我是通过尝试和尝试来解决这个问题的。代码后我给你一个小解释。

      Column(
            children: [
              Text(
                "All Bookings",
                style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: Colors.brown[700]),
              ),
              Expanded(
                child: Container(
                  margin: EdgeInsets.only(top: 24),
                  child: ListView.builder(
                    itemCount: 30,
                    itemBuilder: (BuildContext context, int index) => ListTile(
                      title: Text("List Item ${index + 1}"),
                    ),
                  ),
                ),
              ),
            ],
          )
      

      我要求在 Column 中将标题作为第一个元素,然后放置一个 Listview,以便用户可以拥有滚动列表。这是一种通用的要求。你也可以把它放在底部表或模态中。

      代码说明:

      1. 我让第一个孩子在列内保持标题 ok(我不想滚动,我希望它被修复)
      2. 我已在列内展开子项,这就像获取列中的所有“剩余空间”。
      3. 在里面我保留了容器(只是为了在标题和列表视图之间留一些空间和边距)这是可选的,您可以删除容器,它仍然可以工作。
      4. 现在 Listview 受到很好的约束,它不会尝试在列中无限拉伸。由于 Expanded 小部件已经对其进行了约束。

      如果我在任何地方有错误或此代码不起作用,请纠正我(它现在可以正常工作:)

      【讨论】:

        【解决方案12】:

        你需要做两件事:

        • Column 包裹在SingleChildScrollView
        • ListView 中添加shrinkWrap: truephysics: NeverScrollableScrollPhysics()

        为什么会这样:

        据我了解,NeverScrollableScrollPhysics 禁用滚动 ListView。 所以,滚动适用于SingleChildScrollView。 如果我错了,请在下面评论。

        SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text('Filter'),
              ListView.separated(
                shrinkWrap: true,
                physics: NeverScrollableScrollPhysics(),
                itemCount: rides.length,
                itemBuilder: (BuildContext context, int index) {
                  # return some widget
                }
              ),
        
        

        【讨论】:

          【解决方案13】:

          用扩展的小部件包装您的列表视图

          【讨论】:

          • 您能否详细说明为什么用 Expanded 包装 ListView 可以解决这个问题?
          • 这被其他几个答案的很多所覆盖。请在提交新答案之前查看现有答案。如果您发现以前的答案有用,请将它们作为验证其方法的一种方式进行投票。请不要重复答案,除非您有显着更多细节要添加。
          【解决方案14】:

          就我而言,我正在使用

          • singleChildScrollView
          • 容器
          • 未来建设者 - 列表视图

          我想用整列滚动最后一个滚动视图 为此添加

          physics: NeverScrollableScrollPhysics(),
          

          列表视图中的这一行。

          【讨论】:

            【解决方案15】:

            尝试使用 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),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            )
            

            【讨论】:

              【解决方案16】:
              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),
                    ),
                  ),
                );
              

              【讨论】:

                【解决方案17】:

                另外,你可以试试CustomScrollView

                CustomScrollView(
                      controller: _scrollController,
                      slivers: <Widget>[
                        SliverList(
                          delegate: SliverChildBuilderDelegate(
                            (BuildContext context, int index) {
                              final OrderModel order = _orders[index];
                
                              return Container(
                                margin: const EdgeInsets.symmetric(
                                  vertical: 8,
                                ),
                                child: _buildOrderCard(order, size, context),
                              );
                            },
                            childCount: _orders.length,
                          ),
                        ),
                        SliverToBoxAdapter(
                          child: _buildPreloader(context),
                        ),
                      ],
                    );
                

                提示:_buildPreloader 返回CircularProgressIndicatorText

                在我的情况下,我想在 ListView 下显示一些小部件。使用Column 对我不起作用,因为 Column 内 ListView 周围的小部件始终在屏幕上“向上”显示,例如“绝对位置”

                对不起我的英语不好

                【讨论】:

                  猜你喜欢
                  • 2018-11-16
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-10-03
                  • 2020-10-28
                  • 2022-12-07
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多