使用其他小部件在可滚动列中展开ListView.Builder()

时间:2018-06-11 09:06:41

标签: listview scrollview flutter

我有一个带有大量不同视图的TabBarView()。我希望它们是一个顶部有TextField的列,下面是ListView.Builder(),但两个小部件应该在同一个可滚动区域(scrollview)。我实现它的方式引发了一些错误:

@override
Widget build(BuildContext context) {
return new Column(
  mainAxisAlignment: MainAxisAlignment.center,
    mainAxisSize: MainAxisSize.max,
    children: <Widget>[
      new Padding(
          padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
          child: new TextField(
            decoration: new InputDecoration(
                hintText: "Type in here!"
            ),
          )
      ),
      new ListView.builder(
          itemCount: _posts.length, itemBuilder: _postBuilder)
    ],
   );
}

错误:

I/flutter (23520): The following assertion was thrown during performResize():
I/flutter (23520): Vertical viewport was given unbounded height.
I/flutter (23520): Viewports expand in the scrolling direction to fill their container.In this case, a vertical
I/flutter (23520): viewport was given an unlimited amount of vertical space in which to expand. This situation
I/flutter (23520): typically happens when a scrollable widget is nested inside another scrollable widget.
I/flutter (23520): If this widget is always nested in a scrollable widget there is no need to use a viewport because
I/flutter (23520): there will always be enough vertical space for the children. In this case, consider using a Column
I/flutter (23520): instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size
I/flutter (23520): the height of the viewport to the sum of the heights of its children.

我读到了在Expanded-Area中堆叠ListView.builder(),但它使文本字段变得“粘”,这不是我想要的。 :-)

我也遇到过CustomScrollView,但没有完全理解如何实现它。

提前致谢!

14 个答案:

答案 0 :(得分:23)

将ListView放在Expanded窗口小部件中可以解决您的问题:

@override
Widget build(BuildContext context) {
return new Column(
  mainAxisAlignment: MainAxisAlignment.center,
    mainAxisSize: MainAxisSize.max,
    children: <Widget>[
      new Padding(
          padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
          child: new TextField(
            decoration: new InputDecoration(
                hintText: "Type in here!"
            ),
          )
      ),
      new Expanded(child: ListView.builder(
          itemCount: _posts.length, itemBuilder: _postBuilder))
    ],
   );
}

答案 1 :(得分:8)

解决方案

SingleChildScrollView(
          child: Column(
            children: <Widget>[
                      ListView.builder(
                      shrinkWrap: true,
                      physics: NeverScrollableScrollPhysics(),

此处使用了两个属性

shrinkWrap: true

仅占用所需的空间(当有更多项目时,它仍会滚动)。

physics: NeverScrollableScrollPhysics()

滚动物理,不允许用户滚动。仅表示Column + SingleChildScrollView滚动工作。

答案 2 :(得分:7)

ListView.Builder()中使用 physics:NeverScrollableScrollPhysics() shrinkWrap:true 并享受

答案 3 :(得分:6)

这是解决方案:

SingleChildScrollView(
        physics: ScrollPhysics(),
        child: Column(
          children: <Widget>[
             Text('Hey'),
             ListView.builder(
                physics: NeverScrollableScrollPhysics(),
                shrinkWrap: true,
                itemCount:18,
                itemBuilder: (context,index){
                  return  Text('Some text');
                })
          ],
        ),
      ),

答案 4 :(得分:2)

只需添加

Column(
mainAxisSize: MainAxisSize.max, //Add this line onyour column
children:[
    SomeWidget(),
    Expanded(child:ListView.builder())
  ]
)

答案 5 :(得分:1)

错误原因:

Column沿主轴方向(垂直轴)扩展到最大尺寸,ListView

也扩展

解决方案

您需要限制ListView的高度,以便它可以扩展以匹配Column,有几种方法可以解决此问题,在此列出了一些方法:


  1. 如果要允许ListView占用Column内的所有剩余空间,请使用Flexible

    Column(
      children: <Widget>[
        Flexible(
          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
        )
      ],
    )
    

答案 6 :(得分:1)

就未来而言,我做到了:

SingleChildScrollView(
      physics: ScrollPhysics(),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Text("Hey ho let's go!"),
          
          Flexible(
            child: FutureBuilder(
              future: getData(),
              builder: (BuildContext context,
                  AsyncSnapshot<List<Sale>> snapshot) {
                

                if (snapshot.connectionState != ConnectionState.done ||
                    snapshot.hasData == null) {
                  
                    return CircularProgressIndicator();

                } else {
                  data = snapshot.data;
                  return ListView.builder(
                      physics: NeverScrollableScrollPhysics(),
                      shrinkWrap: true,
                      itemBuilder: (BuildContext context, int index) {
                        return dataItemWidget(size, data[index], context);
                      },
                      itemCount: data.length,
                    );
                }
              },
            ),
          ),
        ],
      ),
    ),

答案 7 :(得分:0)

Column不可滚动,这就是为什么顶部的TextField不会滚动,但底部的ListView会滚动。

我认为解决此问题的最佳方法是将TextField作为ListView中的第一项。

因此,您不需要列,您的父窗口小部件是ListView,其子窗口是TextField,其后是您使用_postBuilder构建的其余项目。

答案 8 :(得分:0)

最好的方法是使列成为可滚动的,方法是使SingleChildScrollView的列成为子代,然后将相同的ScrollController分配给SingleChildScrollView和ListView.builder。这将使文本字段和下面的ListView可滚动。

答案 9 :(得分:0)

使用 Expanded 小部件进行约束,而不会使这些像素溢出:)

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

答案 10 :(得分:0)

只需在 ListView.builder()中添加 physics:NeverScrollableScrollPhysics(),即可滚动

答案 11 :(得分:0)

physics: NeverScrollableScrollPhysics()方法内添加Listview.builder(),嵌套的Listview将滚动

答案 12 :(得分:0)

  1. 返回列( 孩子们: [ 文本(“热门类别”), 扩展( 孩子:ListView.builder(enter code here 收缩包装:假, 滚动方向:Axis.horizo​​ntal, itemCount: 3, itemBuilder:(上下文,索引){ 返回行( crossAxisAlignment: CrossAxisAlignment.start, 孩子们: [ 文本(“你好”), ], ); }), ) ], );

答案 13 :(得分:-1)

这是一个有效的解决方案:

class NestedListExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: [
        const SliverToBoxAdapter(
          child: Text('Header'),
        ),
        SliverList(
          delegate: SliverChildBuilderDelegate(
            (ctx, index) {
              return ListTile(title:Text('Item $index'));
            },
          ),
        ),
      ],
    );
  }
}

这是飞镖板上的preview

您可以将SliverToBoxAdapter用于其他子项,因为只有Sliver可以是CustomScrollView的直接子项。

如果所有列表项的高度都相同,则可以使用SliverFixedExtentList,这样效率更高,因为不是每个孩子的身高都是即时计算出来的,但是您必须知道确切的像素高度。您还可以使用SliverPrototypeExtentList,在其中提供列表中的第一项(原型),所有其他子级将使用原型的高度,因此您无需知道确切的像素高度