如何将ListView添加到Flutter中的列?

时间:2017-08-14 07:12:49

标签: listview layout flutter flutter-layout

我正在尝试为我的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),
          ),
        ),
      );

16 个答案:

答案 0 :(得分:109)

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

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

答案 1 :(得分:29)

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

  

在performResize()期间抛出以下断言:   水平视口被赋予无限高度。   视口在十字轴上展开以填充其容器并限制其子项匹配   它们在横轴上的范围。在这种情况下,水平视口被给予无限量   垂直空间可以扩展。

您需要在水平列表中添加高度约束。例如。用高度包装容器:

new Container(
  height: 44.0,
  child: 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"),
      )
    ],
  ),
)

答案 2 :(得分:24)

Expanded Widget的大小会随着可用空间的增加而增加。由于ListView本质上具有无限的高度,因此会导致错误。

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

在这里,我们应该使用“灵活”窗口小部件,因为即使没有足够的窗口小部件来全屏显示,它也只会占用“展开”全屏显示所需的空间。

答案 3 :(得分:10)

实际上,当您阅读文档时,ListView应该位于Expanded Widget内,以便它可以工作。

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

}

答案 4 :(得分:9)

就像上面其他人提到的那样,用Expanded包装列表视图是解决方案。

但是,当您处理嵌套的列时,还需要将ListView限制为一定的高度(很多时候面对这个问题)。

如果还有其他解决方案,请在评论中提及或添加答案。

示例

std::complex

答案 5 :(得分:5)

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

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

);

答案 6 :(得分:4)

这是一个非常简单的方法。可以采用不同的方法,例如可以通过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"))
            ]),
      ),
    

这三个输出都将是这样

enter image description here

答案 7 :(得分:3)

使用扩展以适合列中的列表视图

demo_glm <- glm(cbind(COUNT, EXPOSURE) ~ height + weight, data, "poisson")
...

答案 8 :(得分:2)

  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中的属性

答案 9 :(得分:2)

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

enter image description here

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

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

有一个简单的解决方法,坦率地说,我是通过尝试和试验找到的。让我在代码后给你一个小解释。

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

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

答案 10 :(得分:0)

错误原因:

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

答案 11 :(得分:0)

我有SingleChildScrollView作为父母,还有一个Column小部件,然后有List View小部件作为最后一个孩子。

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

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

答案 12 :(得分:0)

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

答案 13 :(得分: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),
      ),
    ),
  );

答案 14 :(得分:0)

另外,您可以尝试使用 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 周围的小部件始终在屏幕上显示“向上”,例如“绝对位置”

抱歉我的英语不好

答案 15 :(得分:0)

你需要做两件事:

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

为什么有效:

据我所知,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
        }
      ),