当组件内容超过当前显示视口(ViewPort)时,如果没有特殊处理,Flutter 则会提示 Overflow 错误。为此,Flutter 提供了多种可滚动组件(Scrollable Widget)用于显示列表和长布局。
Scrollable
可滚动组件都直接或间接包含一个 Scrollable 组件
Scrollable({
...
this.axisDirection = AxisDirection.down,
this.controller,
this.physics,
@required this.viewportBuilder,
})
参数
- axisDirection:滚动方向。
- physics:此属性接受一个
ScrollPhysics
类型的对象,它决定可滚动组件如何响应用户操作,比如用户滑动完抬起手指后,继续执行动画;或者滑动到边界时,如何显示。默认情况下,Flutter 会根据具体平台分别使用不同的 ScrollPhysics 对象,应用不同的显示效果,如当滑动到边界时,继续拖动的话,在 iOS 上会出现弹性效果,而在 Android 上会出现微光效果。- Flutter SDK 中包含了两个 ScrollPhysics 的子类,他们可以直接使用:
ClampingScrollPhysics
Android 下微光效果。BouncingScrollPhysics
iOS 下弹性效果。
- Flutter SDK 中包含了两个 ScrollPhysics 的子类,他们可以直接使用:
- controller:此属性接受一个 ScrollController 对象。ScrollController 的主要作用是控制滚动位置和监听滚动事件。
SingleChildScrollView
SingleChildScrollView 就是普通的滚动视图, 允许存在单个子节点
SingleChildScrollView({
this.scrollDirection = Axis.vertical,
this.reverse = false,
this.padding,
bool primary,
this.physics,
this.controller,
this.child,
})
参数
scrollDirection
滚动方向,默认是垂直方向Axis.vertical
垂直方向Axis.horizontal
水平方向
reverse
是否按照阅读方向相反的方向滑动primary
指是否使用 widget 树中默认的 PrimaryScrollController;当滑动方向为垂直方向(scrollDirection 值为 Axis.vertical)并且没有指定 controller 时,primary 默认为 true.
示例: 垂直方向滚动
Scrollbar(
child: SingleChildScrollView(
padding: EdgeInsets.all(16.0),
child: Center(
child: Column(
children: "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("").map((c) =>
Text(c, textScaleFactor: 2.0,)).toList(),
),
),
),
)
效果:
示例: 水平方向滚动
crollbar(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
padding: EdgeInsets.all(16.0),
child: Center(
child: Row(
children: "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("").map((c) =>
Text(c, textScaleFactor: 2.0,)).toList(),
),
),
),
),
效果:
Scrollbar
Scrollbar 是一个 Material 风格的滚动指示器(滚动条),如果要给可滚动组件添加滚动条,只需将 Scrollbar 作为可滚动组件的任意一个父级组件即可
Scrollbar 和 CupertinoScrollbar 都是通过 ScrollController 来监听滚动事件来确定滚动条位置的。
相关概念
ViewPort 视口
在很多布局系统中都有 ViewPort 的概念,在 Flutter 中,术语 ViewPort(视口),如无特别说明,则是指一个 Widget 的实际显示区域。例如,一个 ListView 的显示区域高度是 800 像素,虽然其列表项总高度可能远远超过 800 像素,但是其 ViewPort 仍然是 800 像素。
基于 Sliver 的延迟构建
通常可滚动组件的子组件可能会非常多、占用的总高度也会非常大;如果要一次性将子组件全部构建出将会非常昂贵!为此,Flutter 中提出一个 Sliver(中文为“薄片”的意思)概念,如果一个可滚动组件支持 Sliver 模型,那么该滚动可以将子组件分成好多个“薄片”(Sliver),只有当 Sliver 出现在视口中时才会去构建它,这种模型也称为“基于 Sliver 的延迟构建模型”。可滚动组件中有很多都支持基于 Sliver 的延迟构建模型,如 ListView、GridView,但是也有不支持该模型的,如 SingleChildScrollView。
主轴和纵轴
在可滚动组件的坐标描述中,通常将滚动方向称为主轴,非滚动方向称为纵轴。由于可滚动组件的默认方向一般都是沿垂直方向,所以默认情况下主轴就是指垂直方向,水平方向同理。
其他
- CupertinoScrollbar 是 iOS 风格的滚动条,如果你使用的是 Scrollbar,那么在 iOS 平台它会自动切换为 CupertinoScrollbar。