我有一个带有大量不同视图的 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 但没有完全理解如何实现它。
解决方案如下:
SingleChildScrollView(
physics: ScrollPhysics(),
child: Column(
children: <Widget>[
Text('Hey'),
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount:18,
itemBuilder: (context,index){
return Text('Some text');
})
],
),
),
将 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))
],
);
}
使用
SingleChildScrollView
允许子部件滚动
解决方案
SingleChildScrollView(
child: Column(
children: <Widget>[
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
这里使用了两个属性
shrinkWrap: true
只占用它需要的空间(当有更多项目时它仍然会滚动)。
physics: NeverScrollableScrollPhysics()
滚动物理不允许用户滚动。意味着只有Column+SingleChildScrollView滚动起作用。
错误原因:
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
)
],
)
在 ListView.Builder() 中使用 physical: NeverScrollableScrollPhysics() 和 shrinkWrap: true 并享受
这是一个有效的解决方案:
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 上的预览。
您可以对其他子级使用 SliverToBoxAdapter,因为只有 Sliver 可以成为 CustomScrollView 的直接子级。
如果所有列表项的高度相同,那么您可以使用 SliverFixedExtentList,这更有效,因为每个子项的高度不是即时计算的,但您必须知道确切的像素高度。您还可以使用 SliverPrototypeExtentList,在其中提供列表中的第一项(原型),所有其他子项将使用原型的高度,因此您不需要知道确切的像素高度。
使用 Expanded 小部件进行约束而不溢出这些像素,:)
Column(
children: <Widget>[
Expanded(
child: ListView(),
),
Expanded(
child: ListView(),
),
],
)
只需添加
Column(
mainAxisSize: MainAxisSize.max, //Add this line onyour column
children:[
SomeWidget(),
Expanded(child:ListView.builder())
]
)
就我的未来而言,我是这样做的:
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,
);
}
},
),
),
],
),
),
//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));}))
),]),
最好的方法是通过将列设置为 SingleChildScrollView 的子级,然后将相同的 ScrollController 分配给 SingleChildScrollView 和 ListView.builder 来使列可滚动。这将使文本字段和下面的 ListView 可滚动。
只需在 ListView.builder() 中添加 physicals: NeverScrollableScrollPhysics() 即可滚动
在
physics: NeverScrollableScrollPhysics()
方法中添加 Listview.builder()
,嵌套的 Listview
将滚动
Column
不可滚动,这就是为什么顶部的 TextField
不会滚动,但底部的 ListView
会滚动。
我认为解决此问题的最佳方法是将您的
TextField
设为 ListView
中的第一项。
因此您不需要列,您的父小部件是
ListView
,其子小部件是 TextField
,后跟您使用 _postBuilder
构建的其余项目。
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"),
],
);
}),
),
],
);
body: SingleChildScrollView(
physics: ScrollPhysics(),
child: Column(
children: [
getFiltersOnHomePage(),
SizedBox(
child: StreamBuilder(
stream: FirebaseFirestore.instance.collection('posts').snapshots(),
builder: (context,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: snapshot.data!.docs.length,
itemBuilder: (ctx, index) => Container(
margin: EdgeInsets.symmetric(
horizontal: width > webScreenSize ? width * 0.3 : 0,
vertical: width > webScreenSize ? 15 : 0,
),
child: PostCard(
snap: snapshot.data!.docs[index].data(),
),
));
},
),
),
],
),
),[enter image description here][1]***You will be able to scroll through the page by using Expanded Widget
块引用 使用它您可以滚动整个页面。此页面包含一行和可滚动列内的列表视图构建器。
在我的例子中,我添加了一个透明颜色且高度达到 270 的 Container 来解决这个问题。
Column(
children: <Widget>[
ListView(
shrinkWrap: true, // use it
),
Container(
color: Colors.transparent,
height: 270.0,
),
],
)
只需在列表视图生成器中使用物理,然后它将可以滚动。
`ListView.builder(
**physics: ScrollPhysics(),**
shrinkWrap: true,
itemCount: rentalTypes.length,
itemBuilder: (BuildContext context,index){
String details = rentalTypes[index]['houseDetails'];
String rent = rentalTypes[index]['rent'];
return PostItem(image: AssetImage("assets/images/bedroom.jpg"), description: details, price: rent);
}
),`