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

aks*_*ksn 14 dart flutter flutter-layout

我有一个带有大量不同视图的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)
    ],
   );
}
Run Code Online (Sandbox Code Playgroud)

错误:

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.
Run Code Online (Sandbox Code Playgroud)

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

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

提前致谢!

小智 161

这是解决方案:

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

  • @PedroMolina您是否在“ListView”中添加了“shrinkWrap:true”,因为没有它它也可以工作。不过感谢@SunpreetSingh (4认同)
  • 我希望我能对此点赞 100 次……终于成功了。 (2认同)
  • 可以接受的答案:) (2认同)

小智 45

将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))
    ],
   );
}
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的方法,应该是公认的答案,因为它满足了我们不希望整个页面滚动而只滚动列表视图的用例。 (3认同)
  • 据我了解,Expanded 和 ListView 一起工作,因为 Expanded 使用屏幕的其余部分。因此,如果您想要在“扩展”下方有一个按钮,则首先需要填充文本字段,然后是“扩展”(可滚动),然后是屏幕底部的“按钮”。 (2认同)

jit*_*555 28

使用SingleChildScrollView它允许子小部件滚动

解决方案

SingleChildScrollView(
          child: Column(
            children: <Widget>[
                      ListView.builder(
                      shrinkWrap: true,
                      physics: NeverScrollableScrollPhysics(),
Run Code Online (Sandbox Code Playgroud)

这里使用的两个属性

shrinkWrap: true
Run Code Online (Sandbox Code Playgroud)

只占用它需要的空间(当有更多项目时它仍然会滚动)。

physics: NeverScrollableScrollPhysics()
Run Code Online (Sandbox Code Playgroud)

不允许用户滚动的滚动物理。意味着只有 Column+SingleChildScrollView 滚动工作。


jin*_*yus 17

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

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'));
            },
          ),
        ),
      ],
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

这是dartpad 上的预览

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

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

  • 这是最好的解决方案。`NeverScrollablePhysics()` 和 `shrinkwrap: true` 完全违背了 ListView.builder 的目的 - 即优化大型列表的性能。使用 SliverList 和 CustomScrollView,您可以在另一个滚动体内获得列表构建器的出色性能...就像您有一堆表单元素在下面生成一个长列表,并且您需要所有内容一起滚动。 (6认同)

小智 16

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


Cop*_*oad 15

错误原因:

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

解决方案

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


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

    Column(
      children: <Widget>[
        Flexible(
          child: ListView(...),
        )
      ],
    )
    
    Run Code Online (Sandbox Code Playgroud)

  1. 如果你想限制你ListView的某些height,你可以使用SizedBox.

    Column(
      children: <Widget>[
        SizedBox(
          height: 200, // constrain height
          child: ListView(),
        )
      ],
    )
    
    Run Code Online (Sandbox Code Playgroud)

  1. 如果你的ListView孩子很小,你可以试试shrinkWrap财产。

    Column(
      children: <Widget>[
        ListView(
          shrinkWrap: true, // use it
        )
      ],
    )
    
    Run Code Online (Sandbox Code Playgroud)

  • 第三号解决了我的问题。谢谢,很好的答案! (2认同)

小智 9

只需添加

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


小智 6

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

Column(
  children: <Widget>[
    Expanded(
      child: ListView(),
    ),
    Expanded(
      child: ListView(),
    ),
  ],
)
Run Code Online (Sandbox Code Playgroud)


Ped*_*ina 6

就我的未来而言,我是这样做的:

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,
                    );
                }
              },
            ),
          ),
        ],
      ),
    ),
Run Code Online (Sandbox Code Playgroud)


小智 5

//If you want Listview.builder inside ListView and want to scroll the parent ListView// //whenever the Items in ListView.builder ends or start you can do it like this
       body: ListView(
                  physics: ScrollPhysics(),
                  children: [
                    SizedBox(height: 20),
                    Container( height: 110.0 *5, // *5 to give size to the container //according to items in the ListView.builder. Otherwise will give hasSize Error
                    child:ListView.builder(
                       physics: NeverScrollableScrollPhysics(),
                       scrollDirection: Axis.vertical,
                       itemCount: 5,
                        itemBuilder: (BuildContext context, int indexChild) {
                         return InkWell(child:Container(height:100));}))                
                    ),]),
Run Code Online (Sandbox Code Playgroud)


Edm*_*man 1

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

我认为解决这个问题的最佳方法是将您的TextField第一项设置为ListView.

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