当组件内容超过当前显示视口(ViewPort)时,如果没有特殊处理,Flutter则会提示Overflow错误。因此,Flutter提供了多种可滚动组件(Scrollable Widget)用于显示列表和长布局。
可滚动组件都直接或间接包含一个Scrollable组件。
Scrollable({
this.axisDirection = AxisDirection.down,
this.controller,
this.physics,
})
axisDirection
滚动方向。
physics
默认情况下,Flutter会根据具体平台分别使用不同的ScrollPhysics对象,应用不同的显示效果。
ClampingScrollPhysics:Android下微光效果。
BouncingScrollPhysics:iOS下弹性效果。
controller:
此属性接受一个ScrollController对象。ScrollController的主要作用是控制滚动位置和监听滚动事件。默认情况下,Widget树中会有一个默认的PrimaryScrollController,如果子树中的可滚动组件没有显式的指定controller,并且primary属性值为true时(默认就为true),可滚动组件会使用这个默认的PrimaryScrollController。
Scrollbar
Scrollbar是一个Material风格的滚动指示器(滚动条),如果要给可滚动组件添加滚动条,只需将Scrollbar作为可滚动组件的任意一个父级组件即可
Scrollbar(
child: SingleChildScrollView(
...
),
);
CupertinoScrollbar
CupertinoScrollbar是iOS风格的滚动条,如果你使用的是Scrollbar,那么在iOS平台它会自动切换为CupertinoScrollbar。
ViewPort
在Flutter中,术语ViewPort(视口),如无特别说明,则是指一个Widget的实际显示区域。
基于Sliver的延迟构建
可滚动组件的子组件可能会非常多、占用的总高度也会非常大;一个可滚动组件支持Sliver模型,那么该滚动可以将子组件分成好多个“薄片”(Sliver),只有当Sliver出现在视口中时才会去构建它,这种模型也称为“基于Sliver的延迟构建模型”。
SingleChildScrollView
SingleChildScrollView类似于Android中的ScrollView,它只能接收一个子组件
reverse:
是否按照阅读方向相反的方向滑动
primary:
指是否使用widget树中默认的PrimaryScrollController;当滑动方向为垂直方向(scrollDirection值为Axis.vertical)并且没有指定controller时,primary默认为true.
例
import 'package:flutter/material.dart';
class StudySingleChildScrollView extends StatelessWidget{
@override
Widget build(BuildContext context) {
String letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZXYZNYCABCDEFG";
return Scaffold(
appBar: AppBar(
title: Text("SingleChildScrollView"),
),
body: Scrollbar(//显示滚动条
child: SingleChildScrollView(
padding: const EdgeInsets.all(10),
child:Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: letter.split("").map((e) => Text(e,style: TextStyle(
fontSize: 36,
),)).toList(),
),
width: double.infinity,
),
),
),
);
}
}
效果
通常SingleChildScrollView只应在内容不会超过屏幕太多时使用,因为SingleChildScrollView不支持基于Sliver的延迟实例化模型,所以如果预计视口可能包含超出屏幕尺寸太多的内容时,不建议使用SingleChildScrollView。