目录
[shrinkWrap 属性](#shrinkWrap 属性)
引
当我们构建界面,很多时候都会需要显示一个能滑动的流布局,同时这个布局还要有些其他的界面元素,同时在flutter中,滑动的界面嵌套listview会导致滑动手势冲突,本文针对此包含多个元素和一个ListView
的复杂界面给出了一种较好的布局方式,写此篇博客也算是为笔者记录一下,备注,本文不涵盖滑动后,部分元素能固定一直显示的代码,这个也有一些其他的方式实现
代码以及概叙
- 总体是使用
Column
包裹在SingleChildScrollView
内作为父组件,这样可以确保所有内容都可以通过滚动来访问 - 同时需要注意直接将
ListView
放在SingleChildScrollView
中会导致滚动冲突,因为它们都试图响应滑动手势 - 为了解决这个问题需要将
ListView
的shrinkWrap
属性设置为true
,这样ListView
就会占用其内容的实际大小,而不是尽可能多地占用空间 - 同时还需要将
physics
属性设置为NeverScrollableScrollPhysics
,以阻止ListView
自己滚动,而是让SingleChildScrollView
来处理滚动
Dart
class ComplexScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('复杂界面'),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
// 其他元素
Container(
padding: EdgeInsets.all(16.0),
child: Text('界面顶部内容'),
),
// 这里是ListView
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: 20,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text('列表项 $index'),
);
},
),
// 更多内容
Container(
padding: EdgeInsets.all(16.0),
child: Text('界面底部内容'),
),
],
),
),
);
}
}
详细解释
SingleChildScrollView
SingleChildScrollView
是 Flutter 中的一个滚动组件,它可以包含一个单个的子组件,并提供滚动功能。这个组件特别适合于只有一个直接子组件且子组件的大小超出屏幕大小的情况。它与其他滚动组件(如ListView
或GridView
)不同,后者都是为展示一系列的子组件而设计的。
SingleChildScrollView
对于创建可滚动的自定义布局特别有用,如组合了多种类型的子组件(如Column
、Row
、Container
、GridView
等)的复杂页面布局。
使用SingleChildScrollView
时要注意:
- 它不应该包含多个能够滚动的子组件,因为这会导致滚动冲突。
- 它不是非常适用于包含大量子元素的长列表,因为这样的列表应该使用专门的列表组件如
ListView
,这些组件具有更高效的元素回收机制。
现在让我们来看看shrinkWrap
属性和NeverScrollableScrollPhysics
。
shrinkWrap 属性
在ListView
中,shrinkWrap
属性决定了列表的长度是否应该仅仅包裹它的内容。默认情况下,ListView
会尝试尽可能多地占用滚动方向上的空间。这意味着ListView
默认是被设计成滚动的,并且它期望有足够的空间来滚动其内容。但当ListView
被放置在另一个滚动组件内时,如SingleChildScrollView
,就会出现滚动冲突的问题。
设置shrinkWrap
为true
后,ListView
将不再尝试填充额外的空间,而是仅占用其子元素实际需要的空间。这样做,ListView
就不会尝试自己处理滑动事件,从而避免了和`Single
ChildScrollView的冲突,因为此时
ListView`没有自己的滚动行为。
NeverScrollableScrollPhysics
physics
属性决定了滚动组件如何响应用户的滚动手势和其他交互。当你在一个可滚动的父组件中嵌套了一个可滚动的子组件(比如在SingleChildScrollView
中嵌套了ListView
),如果两者都可以滚动,就会导致冲突。
为了避免这个问题,你可以给内部的滚动组件设置NeverScrollableScrollPhysics
。这个物理效果会使得ListView
不再响应滚动操作,所有的滚动都将由外部的SingleChildScrollView
处理。这样,即使ListView
在屏幕上只显示了一部分内容,它也不会尝试滚动这部分内容,用户的滚动手势会传递给SingleChildScrollView
,实现整个页面的统一滚动。