# 可滚动组件

当组件内容超过当前显示视口(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 就是普通的滚动视图, 允许存在单个子节点

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。

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

Design by Quanzaiyu | Power by VuePress