Flutter ListView.Builder() 在可滚动列中与其他小部件
Posted
技术标签:
【中文标题】Flutter ListView.Builder() 在可滚动列中与其他小部件【英文标题】:Flutter ListView.Builder() in scrollable Column with other widgets 【发布时间】:2018-11-20 11:38:35 【问题描述】:我有一个带有大量不同视图的 TabBarView()。我希望它们成为顶部有 TextField 和下方有 ListView.Builder() 的 Column,但两个小部件应位于同一可滚动区域(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.
我阅读了有关在扩展区域中堆叠 ListView.builder() 的信息,但它使文本字段有点“粘性”,这不是我想要的。 :-)
我也遇到过 CustomScrollView,但不完全了解如何实现它。
【问题讨论】:
用展开的小部件包装 ListView 【参考方案1】:解决办法如下:
SingleChildScrollView(
physics: ScrollPhysics(),
child: Column(
children: <Widget>[
Text('Hey'),
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount:18,
itemBuilder: (context,index)
return Text('Some text');
)
],
),
),
【讨论】:
它对我来说并不完全有效,我需要为 columnMainAxisSize.min 添加属性才能使其工作。 @PedroMolina 您是否在您的ListView
中添加了shrinkWrap: true
,因为没有它也可以工作。不过感谢@SunpreetSingh
“物理:NeverScrollableScrollPhysics()”救了我。谢谢!
非常感谢兄弟
你拯救了我的一天。我一直想知道为什么 NeverScrollableScrollPhysics() 甚至存在。现在我知道为什么了:D【参考方案2】:
将 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))
],
);
【讨论】:
据我了解,Expanded 和 ListView 一起工作,因为expanded 使用了屏幕的其余部分。因此,如果您想要展开下方的按钮,您首先需要填充的文本字段,然后展开(可滚动),然后是屏幕底部的按钮。 如果此解决方案有问题,请验证该列是否在定位内。如果是这样,您需要指定顶部和底部。所以飞镖可以计算大小。仅指定 top 将导致计算数据不足。 这是正确的方法,应该是公认的答案,因为它满足了我们不希望整个页面滚动但只滚动列表视图的用例。【参考方案3】:使用SingleChildScrollView
允许子小部件滚动
解决方案
SingleChildScrollView(
child: Column(
children: <Widget>[
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
这里使用了两个属性
shrinkWrap: true
只占用它需要的空间(当有更多项目时它仍然会滚动)。
physics: NeverScrollableScrollPhysics()
不允许用户滚动的滚动物理。意味着只有 Column+SingleChildScrollView 滚动工作。
【讨论】:
此解决方案效率低下,因为列表视图将立即构建所有项目,从而消除了性能优势。 @kemist:那么理想的解决方案是什么? @jitsm555 您想使用带有 SliverList 和 SliverChildBuilderDelegate 的 CustomScrollView。 @jitsm555 检查我的解决方案:***.com/a/65340391/9695723 但是这个解决方案 NotificationListener 不起作用【参考方案4】:错误原因:
Column
扩展到主轴方向(垂直轴)的最大尺寸,ListView
也是如此
解决方案
您需要限制ListView
的高度,使其扩展以匹配Column
,解决此问题有多种方法,我在这里列出一些:
如果您想让ListView
占用Column
内的所有剩余空间,请使用Flexible
。
Column(
children: <Widget>[
Flexible(
child: ListView(...),
)
],
)
如果您想将您的ListView
限制为某个height
,您可以使用SizedBox
。
Column(
children: <Widget>[
SizedBox(
height: 200, // constrain height
child: ListView(),
)
],
)
如果你的ListView
很小,你可以试试shrinkWrap
属性。
Column(
children: <Widget>[
ListView(
shrinkWrap: true, // use it
)
],
)
【讨论】:
3 号解决了我的问题。谢谢,很好的答案! 我收到Incorrect use of ParentDataWidget.
方法1
@PiyushChauhan 你可能错过了包含Column
。如果不是这种情况,请提出一个单独的问题,我很乐意为您提供帮助。
我的 Listview 周围没有灵活的小部件——只有一个 Expanded 小部件围绕它是其后代的 Column 部分。这对我很有帮助,谢谢!【参考方案5】:
在 ListView.Builder() 中使用 physics: NeverScrollableScrollPhysics() 和 shrinkWrap: true 并享受
【讨论】:
【参考方案6】:使用 Expanded 小部件来约束而不溢出这些像素,:)
Column(
children: <Widget>[
Expanded(
child: ListView(),
),
Expanded(
child: ListView(),
),
],
)
【讨论】:
【参考方案7】:添加
Column(
mainAxisSize: MainAxisSize.max, //Add this line onyour column
children:[
SomeWidget(),
Expanded(child:ListView.builder())
]
)
【讨论】:
【参考方案8】:就我的未来而言,我是这样做的:
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,
);
,
),
),
],
),
),
【讨论】:
【参考方案9】://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));))
),]),
【讨论】:
【参考方案10】:这是一个有效的解决方案:
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'));
,
),
),
],
);
这是 dartpad 上的 preview。
您可以为其他孩子使用 SliverToBoxAdapter,因为只有 Sliver 可以是 CustomScrollView 的直接孩子。
如果所有列表项的高度相同,那么您可以使用SliverFixedExtentList,这样更有效,因为每个子项的高度不是即时计算的,但您必须知道确切的像素高度。您还可以使用SliverPrototypeExtentList,在其中提供列表中的第一项(原型),所有其他子项将使用原型的高度,因此您无需知道以像素为单位的确切高度。
【讨论】:
这绝对是任何体面列表的最佳解决方案【参考方案11】:只需在 ListView.builder() 中添加 physics: NeverScrollableScrollPhysics() 即可滚动
【讨论】:
请在答案中包含更多上下文【参考方案12】:在Listview.builder()
方法中添加physics: NeverScrollableScrollPhysics()
,嵌套的Listview
会滚动
【讨论】:
【参考方案13】:Column
不可滚动,这就是为什么顶部的 TextField
不会滚动,而底部的 ListView
会滚动。
我认为解决此问题的最佳方法是将您的TextField
设为ListView
中的第一项。
因此您不需要列,您的父小部件是 ListView
,其子小部件是 TextField
,然后是您使用 _postBuilder
构建的其余项目。
【讨论】:
【参考方案14】:最好的方法是使列可滚动,方法是使列成为 SingleChildScrollView 的子列,然后将相同的 ScrollController 分配给 SingleChildScrollView 和 ListView.builder。这将使文本字段和下面的 ListView 成为可滚动的。
【讨论】:
【参考方案15】:return Column(
children: [
Text("Popular Category"),
Expanded(
child: ListView.builder(`enter code here`
shrinkWrap: false,
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: (context, index)
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("hello"),
],
);
),
),
],
);
【讨论】:
以上是关于Flutter ListView.Builder() 在可滚动列中与其他小部件的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Flutter 中添加 ListView.builder 的填充顶部?
Flutter - ListView.builder:初始滚动位置
Flutter - 另一个 Listview 中的 Listview.builder
Flutter:ListView.builder 中的自动垂直高度
Flutter 应用程序,ListView.builder 首次运行时出现错误。需要重启应用(ListView.builder 和 image_picker)