垂直视口被赋予无限高度
Vertical viewport was given unbounded height
这是我的代码:
@override
Widget build(BuildContext context) {
return new Material(
color: Colors.deepPurpleAccent,
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children:<Widget>[new GridView.count(crossAxisCount: _column,children: new List.generate(_row*_column, (index) {
return new Center(
child: new CellWidget()
);
}),)]
)
);
}
异常如下:
I/flutter ( 9925): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter ( 9925): The following assertion was thrown during performResize():
I/flutter ( 9925): Vertical viewport was given unbounded height.
I/flutter ( 9925): Viewports expand in the scrolling direction to fill their container.In this case, a vertical
I/flutter ( 9925): viewport was given an unlimited amount of vertical space in which to expand. This situation
I/flutter ( 9925): typically happens when a scrollable widget is nested inside another scrollable widget.
I/flutter ( 9925): If this widget is always nested in a scrollable widget there is no need to use a viewport because
I/flutter ( 9925): there will always be enough vertical space for the children. In this case, consider using a Column
I/flutter ( 9925): instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size
I/flutter ( 9925): the height of the viewport to the sum of the heights of its children.
I/flutter ( 9925):
I/flutter ( 9925): When the exception was thrown, this was the stack:
I/flutter ( 9925): #0 RenderViewport.performResize.<anonymous closure> (package:flutter/src/rendering/viewport.dart:827:15)
I/flutter ( 9925): #1 RenderViewport.performResize (package:flutter/src/rendering/viewport.dart:880:6)
I/flutter ( 9925): #2 RenderObject.layout (package:flutter/src/rendering/object.dart:1555:9)
不要使用 Column
进行单子对齐。请改用 Align
。
new Align(
alignment: Alignment.topCenter,
child: new GridView(),
)
将网格视图放入 Flexible
或 Expanded
小部件
return new Material(
color: Colors.deepPurpleAccent,
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children:<Widget>[
Flexible(
child: GridView.count(crossAxisCount: _column,children: new List.generate(_row*_column, (index) {
return new Center(
child: new CellWidget(),
);
}),))]
)
);
加上这两行
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
...
当您尝试在 Column
中使用 ListView
/GridView
时,通常会发生这种情况,有很多解决方法,我在这里列出一些。
将 ListView
换成 Expanded
Column(
children: <Widget>[
Expanded( // wrap in Expanded
child: ListView(...),
),
],
)
将ListView
包裹在SizedBox
中并给出一个有界的height
Column(
children: <Widget>[
SizedBox(
height: 400, // fixed height
child: ListView(...),
),
],
)
在ListView
中使用shrinkWrap: true
。
Column(
children: <Widget>[
ListView(
shrinkWrap: true, // use this
),
],
)
有一个名为“中心”的小部件。它应该可以帮助您实现您想做的事情(垂直居中)。 Official Documentation for Center widget
所以,每个人都发布了答案,但没有人关心解释原因:
我将复制有关 shrinkWrap
:
的文档
Whether the extent of the scroll view in the [scrollDirection] should be
determined by the contents being viewed.
If the scroll view does not shrink wrap, then the scroll view will expand
to the maximum allowed size in the [scrollDirection]. If the scroll view
has unbounded constraints in the [scrollDirection], then [shrinkWrap] must
be true.
Shrink wrapping the content of the scroll view is significantly more
expensive than expanding to the maximum allowed size because the content
can expand and contract during scrolling, which means the size of the
scroll view needs to be recomputed whenever the scroll position changes.
Defaults to false
.
所以,根据文档的词汇,这里发生的是我们的 ListView
处于 无限约束(在我们滚动的方向),因此 ListView
会抱怨:
... a vertical viewport was given an unlimited amount of vertical space in
which to expand.
通过简单地将 shrinkWrap
设置为 true
将确保它包装由内容定义的大小。一个示例代码来说明:
// ...
ListView(
// Says to the `ListView` that it must wrap its
// height (if it's vertical) and width (if it's horizontal).
shrinkWrap: true,
),
// ...
你的代码就是这样,尽管如此,@Rémi 的建议对于这种情况是最好的,使用 Align
而不是 Column
。
当一个可滚动小部件嵌套在另一个可滚动小部件中时,通常会发生这种情况。
在我的例子中,我在 Column 中使用了 GridView 并且抛出了该错误。
GridView 小部件有 shrinkWrap
property/named 参数,设置它 true
我的问题已解决。
GridView.count(
shrinkWrap: true,
// rest of code
)
尽管 shrinkWrap
执行此操作,但您无法在 ListView
中滚动。
如果你想要滚动功能,你可以添加physics
属性:
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: ScrollPhysics(),
...
为第二个列表视图测试这个
ListView.builder(
physics: NeverScrollableScrollPhysics(),
此答案基于@CopsOnRoad
的北边
发生这种情况是因为 ListView/GridView
小部件没有父级来获取它的大小,所以它的高度是无限的并且 flutter 不知道 ListView 的高度并且无法呈现。
方案一:固定高度
直接用Container
或SizedBox
包起来写死高度
Column(
children: <Widget>[
SizedBox(
height: 400, // fixed height
child: ListView(...),
),
],
)
这个可以,但是如果高度需要自适应,写了就不行了
方案二:shrinkWrap: true
尝试 shrinkWrap: true
和 physics: ScrollPhysics()
滚动
shrinkWrap: true
有点像android的wrap_content
.
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: ScrollPhysics()
...
但是编译后,你会发现页面底部有一个长长的黄色警告
所以还是不行
解决方案三:扩展或灵活
Flexible
是flutter中的灵活布局,相当于android.
中的LinearLayout
Flexible中有一个flex
属性,等于layout_weight,占了剩下的全部space。
所以,我们可以用 Flexible 包装 ListView。
Column(
children: <Widget>[
Expanded(
child: ListView(...),
),
],
)
Container(
height: 100,
child: ListView.builder(
scrollDirection: Axis.vertical,
physics: BouncingScrollPhysics(),
shrinkWrap: true,
itemCount: 5,
itemBuilder: (context, index) {
return Text("Hello World $index");
},
),
);
我想 post 另一个答案,因为许多答案(包括已接受的答案!)建议在 ListView.builder
中使用 shrinkWrap: true
。虽然这消除了错误,但对于这种情况,此解决方案是 NOT ideal for performance reasons。 Flutter 设计了 ListView
无限大小,专门为了在必要时阻止这种行为!
Shrink wrapping the content of the scroll view is significantly more expensive than expanding to the maximum allowed size because the content can expand and contract during scrolling, which means the size of the scroll view needs to be recomputed whenever the scroll position changes.
在某些 cases/devices 中,此 属性 导致我的项目出现故障滚动和动画滞后。即使延迟不明显,这个 属性 确实会影响滚动性能。
OP 表明他正在为 ListView
创建一个 小(有限)数量的 children。如果我们想解决这些列表的错误,Google recommends 使用 Flexible
小部件,即列表上的 Expanded
(具有 flex 1 的 Flexible
)本身。
Expanded(
child: ListView(
...
),
)
这里还有其他布局问题,但垂直视口无限高度是因为 ListView
没有限制其大小的 parent。
如果您在 2021 年仍然面临这个问题..这是最好、最简单的解决方案
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
// itemExtent: 400, use this if you give hight of your items
physics: ScrollPhysics(),)
their are many solution .. but they have problem.. like when we use ListView and use its property shrinkWrap .then one thing you many notice the scroll does not work on listView so you must use physics: ScrollPhysics()
解决以上问题的两种方法
1。使用灵活的小部件,
Flexible
小部件可以在行、列中使用,并且 Flex.The 可以灵活扩展以填充主轴中可用的 space(例如,[行的水平方向) ] 或垂直 [Column])
但是,请记住,与 Expanded
不同,Flexible
小部件不需要 child 来填充可用 space。所以,使用 Flexible
.
总是更好
Column(
children: <Widget>[
Flexible(
child: ListView(...),
),
],
)
2。使用 shrinkWrap:true
使用 shrinkWrap
为真,我们告诉 Listview 将其列表呈现为可用 space,而不是低于剩余屏幕。
Column(
children: <Widget>[
ListView(
shrinkWrap: true,
),
],
)
此外,physics
属性可用于 allow/disallow Listview
的滚动
停止滚动
ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
),
允许滚动
ListView(
shrinkWrap: true,
physics: ScrollPhysics(),
),
有很多答案,但每个都有自己的局限性。每个人都在说使用 shrinkWrap: true。是的,你应该使用它,但这些代码的效果是当你滚动列表时,它会自动移动到顶部项目,意味着滚动回到顶部。
所以完美的解决方案是使用 shrinkwrap 和 physics 然后只有列表才能平滑滚动。
shrinkWrap: true, //
physics: ScrollPhysics(), // both line is mandatory
如果您想查看 Listview.builder 的其他示例,其中列作为子项并且列表可以垂直滚动,那么您可以 see the example here - 在垂直列表中排列多个文本。
只想添加我的解决方案,该解决方案适用于我在同一屏幕上具有垂直列表视图以及其他按钮和文本的情况:
Flexible(
child:
ListView.builder(
// make sure to add the following lines:
shrinkWrap: true,
physics: ScrollPhysics(),
// the rest of your list view code
) // ListView
) // Flexible
此解决方案效果很好,尤其是当您在同一屏幕上有其他小部件时。在这种特殊情况下,单独使用“Expand”或“Flexible”是行不通的。
也遇到这个错误,因为代码是这样的
return Container(
child: Column(
children: [
ListView.separated(
itemBuilder: (context, index) {
return CircleManagerSettingItem(widget.membersInfo[index]);
},
separatorBuilder: (_, index) => DD(
height: 1,
paddingLeft: 10,
paddingRight: 10,
),
itemCount: (widget.membersInfo.length)),
],
),
);
把Container
里面的Column
去掉就OK了
在我的例子中,我必须将 ListView 包装在一个容器中并给这个容器一个特定的高度
视口异常原因
GridView
/ ListView
grow until constraints (limits) 停止扩展然后滚动查看超过该尺寸的物品。
但Column
布局其child任无任何约束,完全无视自身尺寸和屏幕尺寸. Column
.
里面有无限个space
Viewport was given unbounded height
发生异常是因为 Grid/ListView
在 Column
.
中扩展到无穷大
Flexible/Expanded
存在给予 Column
children 约束 Column's
大小。 (这两个小部件不能在其他任何地方使用,除了 Row
和 Column
内。)
在 Column
中的 Flexible/Expanded
小部件内,Grid/ListView
仅使用剩余的 space 未被其他 non-flexible 小部件使用,这些小部件首先布置. (布局阶段信息见底部。)
shrinkWrap
不是一个好的解决方案
在 Column
中的 ListView
上使用 shrinkWrap: true
并没有太大帮助,因为:
ListView
不再滚动
ListView
还能溢出
A ListView
高度足以显示其所有项目,不会滚动。可以说违背了使用 ScrollView
小部件(parent class of ListView
)的目的。
在Column
布局阶段1(布局阶段的解释见底部),ListView
可以是任何它想要的高度(没有限制)。
ListView
和 shrinkWrap:true
的高度会增加以显示其所有项目。
有了足够的项目,shrinkWrapped
ListView
会不断增长(它永远不会滚动)以溢出里面的任何 Column
,无论是屏幕还是其他更严格的约束。
不应该 shrinkWrap
只使 ListView
与其项目一样大 或 剩余 space (达到屏幕高度),然后滚动?
这在直觉上是合理的,但是在第 1 阶段的 Column
中 布局是在 无界 space[=177 中完成的=].
所以,剩下的 space 是 unlimited/infinite。永远不会达到最大高度。 shrinkWrap:true
随着项目的添加不断增加 Column
高度,直到溢出屏幕(或其他较小的限制)。
示例shrinkWrap:true
溢出
下面是一个向 Column
中的收缩包裹 ListView
添加项目的示例,直到其高度高于屏幕,创建溢出警告区域:
(只需按住 + 标志浮动操作按钮)
import 'package:flutter/material.dart';
class ColumnListViewPage extends StatefulWidget {
@override
_ColumnListViewPageState createState() => _ColumnListViewPageState();
}
class _ColumnListViewPageState extends State<ColumnListViewPage> {
int _count = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Column & ListView'),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
setState(() {
_count++;
});
},
),
body: SafeArea(
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.red)
),
/// // without center, Column will be as narrow as possible
alignment: Alignment.center,
/// Column is forced (constrained) to match screen dimension,
child: Column(
children: [
Text('Inner (Nested) Column'),
ListView.separated( // ← should be wrapped in Expanded
itemCount: _count,
separatorBuilder: (context, index) => const Divider(),
itemBuilder: (context, index) => Padding(
padding: const EdgeInsets.symmetric(vertical: 38.0),
child: Text('Row $index'),
),
shrinkWrap: true, // should be removed
)
],
),
),
),
);
}
}
对于 Column
中的 GridView/ListView
,在 Expanded
或 Flexible
中换行可能是最安全的解决方案。
扩展/灵活
Expanded
和 Flexible
只能在 Column
内部使用(以及它的同级 Row
等)。
它们必须作为 Column
的直接 children 使用。我们不能在 SizedBox
或其他小部件中“嵌套”Expanded
/Flexible
。仅直属Column
为直属children.
在 Column
中,将 ListView/GridView
放在 Expanded
或 Flexible
中确保它将只使用可用的 space,而不是无限的 space .
Column
→ Expanded
→ ListView
ListView/GridView
inside Expanded/Flexible
in a Column
不需要 shrinkWrap
因为它受到 Expanded/Flexible
的限制(给定最大高度)小部件。因此,当 constrained/defined 高度用完时,ListView/GridView
将停止增长并开始滚动。
列布局阶段
Column
分2阶段布局children:
- 第一无约束(无界space)
- 第二,其余 space 基于
Column's
parent
阶段 1
Column
child not 在 Flexible
或 Expanded
内的任何 Column
将在第 1 阶段无限布局,无限 space 完全忽略屏幕尺寸.
需要垂直 boundary/constraint 来限制其增长的小部件(例如 ListView
)将在阶段 1 中导致 Vertical viewport was given unbounded height
异常,因为 没有垂直边界在无限 space.
大多数小部件都有固有尺寸。例如,Text
仅与其内容和字体一样高 size/style。它不会试图增长来填满 space。 Defined-height 小部件在 Column
布局的第 1 阶段表现良好。
第 2 阶段
任何增长到填充边界的小部件都应该放在 Flexible
或 Expanded
阶段 2 布局中。
第 2 阶段根据其 parent 约束计算 Column's
剩余 space 减去 space 在阶段 1 中使用。剩余的 space 作为约束提供给阶段 2 children。
ListView
例如,只会增长到使用剩余的 space 并停止,避免视口异常。
.
我做了一个自定义函数来解决你的问题。
您可以在您的代码库中直接使用此函数:
Widget horizontalListView(height, width, color, child, margin) {
return Column(
children: [
SizedBox(
height: 200,
child: ListView.builder(
itemCount: 10,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (context,index) {
return Container(
height: height,
width: width,
margin: EdgeInsets.all(margin),
color: color,
child: child
);
}
),
),
],
);
})
P.S。抱歉代码对齐不正确。
如果您使用的是 CustomScrollView
你可以试试 SliverFillRemaining
这是我的代码:
@override
Widget build(BuildContext context) {
return new Material(
color: Colors.deepPurpleAccent,
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children:<Widget>[new GridView.count(crossAxisCount: _column,children: new List.generate(_row*_column, (index) {
return new Center(
child: new CellWidget()
);
}),)]
)
);
}
异常如下:
I/flutter ( 9925): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter ( 9925): The following assertion was thrown during performResize():
I/flutter ( 9925): Vertical viewport was given unbounded height.
I/flutter ( 9925): Viewports expand in the scrolling direction to fill their container.In this case, a vertical
I/flutter ( 9925): viewport was given an unlimited amount of vertical space in which to expand. This situation
I/flutter ( 9925): typically happens when a scrollable widget is nested inside another scrollable widget.
I/flutter ( 9925): If this widget is always nested in a scrollable widget there is no need to use a viewport because
I/flutter ( 9925): there will always be enough vertical space for the children. In this case, consider using a Column
I/flutter ( 9925): instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size
I/flutter ( 9925): the height of the viewport to the sum of the heights of its children.
I/flutter ( 9925):
I/flutter ( 9925): When the exception was thrown, this was the stack:
I/flutter ( 9925): #0 RenderViewport.performResize.<anonymous closure> (package:flutter/src/rendering/viewport.dart:827:15)
I/flutter ( 9925): #1 RenderViewport.performResize (package:flutter/src/rendering/viewport.dart:880:6)
I/flutter ( 9925): #2 RenderObject.layout (package:flutter/src/rendering/object.dart:1555:9)
不要使用 Column
进行单子对齐。请改用 Align
。
new Align(
alignment: Alignment.topCenter,
child: new GridView(),
)
将网格视图放入 Flexible
或 Expanded
小部件
return new Material(
color: Colors.deepPurpleAccent,
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children:<Widget>[
Flexible(
child: GridView.count(crossAxisCount: _column,children: new List.generate(_row*_column, (index) {
return new Center(
child: new CellWidget(),
);
}),))]
)
);
加上这两行
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
...
当您尝试在 Column
中使用 ListView
/GridView
时,通常会发生这种情况,有很多解决方法,我在这里列出一些。
将
ListView
换成Expanded
Column( children: <Widget>[ Expanded( // wrap in Expanded child: ListView(...), ), ], )
将
ListView
包裹在SizedBox
中并给出一个有界的height
Column( children: <Widget>[ SizedBox( height: 400, // fixed height child: ListView(...), ), ], )
在
ListView
中使用shrinkWrap: true
。Column( children: <Widget>[ ListView( shrinkWrap: true, // use this ), ], )
有一个名为“中心”的小部件。它应该可以帮助您实现您想做的事情(垂直居中)。 Official Documentation for Center widget
所以,每个人都发布了答案,但没有人关心解释原因:
我将复制有关 shrinkWrap
:
Whether the extent of the scroll view in the [scrollDirection] should be determined by the contents being viewed.
If the scroll view does not shrink wrap, then the scroll view will expand to the maximum allowed size in the [scrollDirection]. If the scroll view has unbounded constraints in the [scrollDirection], then [shrinkWrap] must be true.
Shrink wrapping the content of the scroll view is significantly more expensive than expanding to the maximum allowed size because the content can expand and contract during scrolling, which means the size of the scroll view needs to be recomputed whenever the scroll position changes.
Defaults to
false
.
所以,根据文档的词汇,这里发生的是我们的 ListView
处于 无限约束(在我们滚动的方向),因此 ListView
会抱怨:
... a vertical viewport was given an unlimited amount of vertical space in which to expand.
通过简单地将 shrinkWrap
设置为 true
将确保它包装由内容定义的大小。一个示例代码来说明:
// ...
ListView(
// Says to the `ListView` that it must wrap its
// height (if it's vertical) and width (if it's horizontal).
shrinkWrap: true,
),
// ...
你的代码就是这样,尽管如此,@Rémi 的建议对于这种情况是最好的,使用 Align
而不是 Column
。
当一个可滚动小部件嵌套在另一个可滚动小部件中时,通常会发生这种情况。
在我的例子中,我在 Column 中使用了 GridView 并且抛出了该错误。
GridView 小部件有 shrinkWrap
property/named 参数,设置它 true
我的问题已解决。
GridView.count(
shrinkWrap: true,
// rest of code
)
尽管 shrinkWrap
执行此操作,但您无法在 ListView
中滚动。
如果你想要滚动功能,你可以添加physics
属性:
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: ScrollPhysics(),
...
为第二个列表视图测试这个
ListView.builder(
physics: NeverScrollableScrollPhysics(),
此答案基于@CopsOnRoad
的北边发生这种情况是因为 ListView/GridView
小部件没有父级来获取它的大小,所以它的高度是无限的并且 flutter 不知道 ListView 的高度并且无法呈现。
方案一:固定高度
直接用
Container
或SizedBox
包起来写死高度Column( children: <Widget>[ SizedBox( height: 400, // fixed height child: ListView(...), ), ], )
这个可以,但是如果高度需要自适应,写了就不行了
方案二:shrinkWrap: true
尝试
shrinkWrap: true
和physics: ScrollPhysics()
滚动shrinkWrap: true
有点像android的wrap_content
.ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, physics: ScrollPhysics() ...
但是编译后,你会发现页面底部有一个长长的黄色警告
所以还是不行
解决方案三:扩展或灵活
中的LinearLayoutFlexible
是flutter中的灵活布局,相当于android.Flexible中有一个
flex
属性,等于layout_weight,占了剩下的全部space。所以,我们可以用 Flexible 包装 ListView。
Column( children: <Widget>[ Expanded( child: ListView(...), ), ], )
Container(
height: 100,
child: ListView.builder(
scrollDirection: Axis.vertical,
physics: BouncingScrollPhysics(),
shrinkWrap: true,
itemCount: 5,
itemBuilder: (context, index) {
return Text("Hello World $index");
},
),
);
我想 post 另一个答案,因为许多答案(包括已接受的答案!)建议在 ListView.builder
中使用 shrinkWrap: true
。虽然这消除了错误,但对于这种情况,此解决方案是 NOT ideal for performance reasons。 Flutter 设计了 ListView
无限大小,专门为了在必要时阻止这种行为!
Shrink wrapping the content of the scroll view is significantly more expensive than expanding to the maximum allowed size because the content can expand and contract during scrolling, which means the size of the scroll view needs to be recomputed whenever the scroll position changes.
在某些 cases/devices 中,此 属性 导致我的项目出现故障滚动和动画滞后。即使延迟不明显,这个 属性 确实会影响滚动性能。
OP 表明他正在为 ListView
创建一个 小(有限)数量的 children。如果我们想解决这些列表的错误,Google recommends 使用 Flexible
小部件,即列表上的 Expanded
(具有 flex 1 的 Flexible
)本身。
Expanded(
child: ListView(
...
),
)
这里还有其他布局问题,但垂直视口无限高度是因为 ListView
没有限制其大小的 parent。
如果您在 2021 年仍然面临这个问题..这是最好、最简单的解决方案
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
// itemExtent: 400, use this if you give hight of your items
physics: ScrollPhysics(),)
their are many solution .. but they have problem.. like when we use ListView and use its property shrinkWrap .then one thing you many notice the scroll does not work on listView so you must use physics: ScrollPhysics()
解决以上问题的两种方法
1。使用灵活的小部件,
Flexible
小部件可以在行、列中使用,并且 Flex.The 可以灵活扩展以填充主轴中可用的 space(例如,[行的水平方向) ] 或垂直 [Column])
但是,请记住,与 Expanded
不同,Flexible
小部件不需要 child 来填充可用 space。所以,使用 Flexible
.
Column(
children: <Widget>[
Flexible(
child: ListView(...),
),
],
)
2。使用 shrinkWrap:true
使用 shrinkWrap
为真,我们告诉 Listview 将其列表呈现为可用 space,而不是低于剩余屏幕。
Column(
children: <Widget>[
ListView(
shrinkWrap: true,
),
],
)
此外,physics
属性可用于 allow/disallow Listview
停止滚动
ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
),
允许滚动
ListView(
shrinkWrap: true,
physics: ScrollPhysics(),
),
有很多答案,但每个都有自己的局限性。每个人都在说使用 shrinkWrap: true。是的,你应该使用它,但这些代码的效果是当你滚动列表时,它会自动移动到顶部项目,意味着滚动回到顶部。 所以完美的解决方案是使用 shrinkwrap 和 physics 然后只有列表才能平滑滚动。
shrinkWrap: true, //
physics: ScrollPhysics(), // both line is mandatory
如果您想查看 Listview.builder 的其他示例,其中列作为子项并且列表可以垂直滚动,那么您可以 see the example here - 在垂直列表中排列多个文本。
只想添加我的解决方案,该解决方案适用于我在同一屏幕上具有垂直列表视图以及其他按钮和文本的情况:
Flexible(
child:
ListView.builder(
// make sure to add the following lines:
shrinkWrap: true,
physics: ScrollPhysics(),
// the rest of your list view code
) // ListView
) // Flexible
此解决方案效果很好,尤其是当您在同一屏幕上有其他小部件时。在这种特殊情况下,单独使用“Expand”或“Flexible”是行不通的。
也遇到这个错误,因为代码是这样的
return Container(
child: Column(
children: [
ListView.separated(
itemBuilder: (context, index) {
return CircleManagerSettingItem(widget.membersInfo[index]);
},
separatorBuilder: (_, index) => DD(
height: 1,
paddingLeft: 10,
paddingRight: 10,
),
itemCount: (widget.membersInfo.length)),
],
),
);
把Container
里面的Column
去掉就OK了
在我的例子中,我必须将 ListView 包装在一个容器中并给这个容器一个特定的高度
视口异常原因
GridView
/ ListView
grow until constraints (limits) 停止扩展然后滚动查看超过该尺寸的物品。
但Column
布局其child任无任何约束,完全无视自身尺寸和屏幕尺寸. Column
.
Viewport was given unbounded height
发生异常是因为 Grid/ListView
在 Column
.
Flexible/Expanded
存在给予 Column
children 约束 Column's
大小。 (这两个小部件不能在其他任何地方使用,除了 Row
和 Column
内。)
在 Column
中的 Flexible/Expanded
小部件内,Grid/ListView
仅使用剩余的 space 未被其他 non-flexible 小部件使用,这些小部件首先布置. (布局阶段信息见底部。)
shrinkWrap
不是一个好的解决方案
在 Column
中的 ListView
上使用 shrinkWrap: true
并没有太大帮助,因为:
ListView
不再滚动ListView
还能溢出
A ListView
高度足以显示其所有项目,不会滚动。可以说违背了使用 ScrollView
小部件(parent class of ListView
)的目的。
在Column
布局阶段1(布局阶段的解释见底部),ListView
可以是任何它想要的高度(没有限制)。
ListView
和 shrinkWrap:true
的高度会增加以显示其所有项目。
有了足够的项目,shrinkWrapped
ListView
会不断增长(它永远不会滚动)以溢出里面的任何 Column
,无论是屏幕还是其他更严格的约束。
不应该 shrinkWrap
只使 ListView
与其项目一样大 或 剩余 space (达到屏幕高度),然后滚动?
这在直觉上是合理的,但是在第 1 阶段的 Column
中 布局是在 无界 space[=177 中完成的=].
所以,剩下的 space 是 unlimited/infinite。永远不会达到最大高度。 shrinkWrap:true
随着项目的添加不断增加 Column
高度,直到溢出屏幕(或其他较小的限制)。
示例shrinkWrap:true
溢出
下面是一个向 Column
中的收缩包裹 ListView
添加项目的示例,直到其高度高于屏幕,创建溢出警告区域:
(只需按住 + 标志浮动操作按钮)
import 'package:flutter/material.dart';
class ColumnListViewPage extends StatefulWidget {
@override
_ColumnListViewPageState createState() => _ColumnListViewPageState();
}
class _ColumnListViewPageState extends State<ColumnListViewPage> {
int _count = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Column & ListView'),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
setState(() {
_count++;
});
},
),
body: SafeArea(
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.red)
),
/// // without center, Column will be as narrow as possible
alignment: Alignment.center,
/// Column is forced (constrained) to match screen dimension,
child: Column(
children: [
Text('Inner (Nested) Column'),
ListView.separated( // ← should be wrapped in Expanded
itemCount: _count,
separatorBuilder: (context, index) => const Divider(),
itemBuilder: (context, index) => Padding(
padding: const EdgeInsets.symmetric(vertical: 38.0),
child: Text('Row $index'),
),
shrinkWrap: true, // should be removed
)
],
),
),
),
);
}
}
对于 Column
中的 GridView/ListView
,在 Expanded
或 Flexible
中换行可能是最安全的解决方案。
扩展/灵活
Expanded
和 Flexible
只能在 Column
内部使用(以及它的同级 Row
等)。
它们必须作为 Column
的直接 children 使用。我们不能在 SizedBox
或其他小部件中“嵌套”Expanded
/Flexible
。仅直属Column
为直属children.
在 Column
中,将 ListView/GridView
放在 Expanded
或 Flexible
中确保它将只使用可用的 space,而不是无限的 space .
Column
→ Expanded
→ ListView
ListView/GridView
inside Expanded/Flexible
in a Column
不需要 shrinkWrap
因为它受到 Expanded/Flexible
的限制(给定最大高度)小部件。因此,当 constrained/defined 高度用完时,ListView/GridView
将停止增长并开始滚动。
列布局阶段
Column
分2阶段布局children:
- 第一无约束(无界space)
- 第二,其余 space 基于
Column's
parent
阶段 1
Column
child not 在 Flexible
或 Expanded
内的任何 Column
将在第 1 阶段无限布局,无限 space 完全忽略屏幕尺寸.
需要垂直 boundary/constraint 来限制其增长的小部件(例如 ListView
)将在阶段 1 中导致 Vertical viewport was given unbounded height
异常,因为 没有垂直边界在无限 space.
大多数小部件都有固有尺寸。例如,Text
仅与其内容和字体一样高 size/style。它不会试图增长来填满 space。 Defined-height 小部件在 Column
布局的第 1 阶段表现良好。
第 2 阶段
任何增长到填充边界的小部件都应该放在 Flexible
或 Expanded
阶段 2 布局中。
第 2 阶段根据其 parent 约束计算 Column's
剩余 space 减去 space 在阶段 1 中使用。剩余的 space 作为约束提供给阶段 2 children。
ListView
例如,只会增长到使用剩余的 space 并停止,避免视口异常。
我做了一个自定义函数来解决你的问题。 您可以在您的代码库中直接使用此函数:
Widget horizontalListView(height, width, color, child, margin) {
return Column(
children: [
SizedBox(
height: 200,
child: ListView.builder(
itemCount: 10,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (context,index) {
return Container(
height: height,
width: width,
margin: EdgeInsets.all(margin),
color: color,
child: child
);
}
),
),
],
);
})
P.S。抱歉代码对齐不正确。
如果您使用的是 CustomScrollView
你可以试试 SliverFillRemaining