可滚动组件

当组件内容超过当前显示视口(ViewPort)时,如果没有特殊处理,Flutter 则会提示 Overflow 错误。为此,Flutter 提供了多种可滚动组件(Scrollable Widget)用于显示列表和长布局。

Scrollable

可滚动组件都直接或间接包含一个 Scrollable 组件

Scrollable({
  ...
  this.axisDirection = AxisDirection.down,
  this.controller,
  this.physics,
   this.viewportBuilder,
})

参数

axisDirection

滚动方向。

physics

此属性接受一个 ScrollPhysics 类型的对象,它决定可滚动组件如何响应用户操作,比如用户滑动完抬起手指后,继续执行动画;或者滑动到边界时,如何显示。默认情况下,Flutter 会根据具体平台分别使用不同的 ScrollPhysics 对象,应用不同的显示效果,如当滑动到边界时,继续拖动的话,在 iOS 上会出现弹性效果,而在 Android 上会出现微光效果。

Flutter SDK 中包含了两个 ScrollPhysics 的子类,他们可以直接使用:

  • ClampingScrollPhysics Android 下微光效果。
  • BouncingScrollPhysics iOS 下弹性效果。

controller

此属性接受一个 ScrollController 对象。ScrollController 的主要作用是控制滚动位置和监听滚动事件。

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 来监听滚动事件来确定滚动条位置的。

CupertinoScrollbar

CupertinoScrollbar 是 iOS 风格的滚动条,如果你使用的是 Scrollbar,那么在 iOS 平台它会自动切换为 CupertinoScrollbar。

相关概念

ViewPort 视口

在很多布局系统中都有 ViewPort 的概念,在 Flutter 中,术语 ViewPort(视口),如无特别说明,则是指一个 Widget 的实际显示区域。例如,一个 ListView 的显示区域高度是 800 像素,虽然其列表项总高度可能远远超过 800 像素,但是其 ViewPort 仍然是 800 像素。

基于 Sliver 的延迟构建

通常可滚动组件的子组件可能会非常多、占用的总高度也会非常大;如果要一次性将子组件全部构建出将会非常昂贵!为此,Flutter 中提出一个 Sliver(中文为“薄片”的意思)概念,如果一个可滚动组件支持 Sliver 模型,那么该滚动可以将子组件分成好多个“薄片”(Sliver),只有当 Sliver 出现在视口中时才会去构建它,这种模型也称为“基于 Sliver 的延迟构建模型”。可滚动组件中有很多都支持基于 Sliver 的延迟构建模型,如 ListView、GridView,但是也有不支持该模型的,如 SingleChildScrollView。

主轴和纵轴

在可滚动组件的坐标描述中,通常将滚动方向称为主轴,非滚动方向称为纵轴。由于可滚动组件的默认方向一般都是沿垂直方向,所以默认情况下主轴就是指垂直方向,水平方向同理。

MIT Licensed | Copyright © 2018-present 滇ICP备16006294号

Design by Quanzaiyu | Power by VuePress