
- Flutter和Dart系列文章和代码GitHub地址
- 在
Flutter中, 当内容超过显示视图时,如果没有特殊处理,Flutter则会提示Overflow错误 Flutter提供了多种可滚动(Scrollable Widget)用于显示列表和长布局- 可滚动
Widget都直接或间接包含一个Scrollable, 下面是常用的几个可滚动的WidgetSingleChildScrollViewListViewGridViewCustomScrollView- 滚动监听及控制
ScrollController
Scrollbar
Scrollbar是一个Material风格的滚动指示器(滚动条),如果要给可滚动widget添加滚动条,只需将Scrollbar作为可滚动widget的父widget即可CupertinoScrollbar是iOS风格的滚动条,如果你使用的是Scrollbar,那么在iOS平台它会自动切换为CupertinoScrollbarScrollbar和CupertinoScrollbar都是通过ScrollController来监听滚动事件来确定滚动条位置,关于ScrollController详细的内容我们将在后面专门一节介绍- 下面是
Scrollbar和CupertinoScrollbar的构造函数, 都只有一个child属性, 用于接受一个可滚动的Widget
const Scrollbar({
Key key,
@required this.child,
})
const CupertinoScrollbar({
Key key,
@required this.child,
})
主轴和纵轴
- 在可滚动
widget的坐标描述中,通常将滚动方向称为主轴,非滚动方向称为纵轴。 - 由于可滚动
widget的默认方向一般都是沿垂直方向,所以默认情况下主轴就是指垂直方向,水平方向同理
SingleChildScrollView
SingleChildScrollView类似于开发中常用的ScrollView, 不再详细介绍了, 下面看一下具体使用介绍吧
const SingleChildScrollView({
Key key,
// 设置滚动的方向, 默认垂直方向
this.scrollDirection = Axis.vertical,
// 设置显示方式
this.reverse = false,
// 内边距
this.padding,
// 是否使用默认的controller
bool primary,
// 设置可滚动Widget如何响应用户操作
this.physics,
this.controller,
this.child,
})
scrollDirection
设置视图的滚动方向(默认垂直方向), 需要对应的设置其子Widget是Column或者Row, 否则会报Overflow错误
scrollDirection: Axis.vertical,
// 枚举值
enum Axis {
/// 水平滚动
horizontal,
/// 垂直滚动
vertical,
}
reverse
- 是否按照阅读方向相反的方向滑动
- 设置水平滚动时
- 若
reverse: false,则滚动内容头部和左侧对其, 那么滑动方向就是从左向右 reverse: true时,则滚动内容尾部和右侧对其, 那么滑动方向就是从右往左。
- 若
- 其实此属性本质上是决定可滚动
widget的初始滚动位置是在头还是尾,取false时,初始滚动位置在头,反之则在尾
physics
- 此属性接受一个
ScrollPhysics对象,它决定可滚动Widget如何响应用户操作 - 比如用户滑动完抬起手指后,继续执行动画;或者滑动到边界时,如何显示。
- 默认情况下,
Flutter会根据具体平台分别使用不同的ScrollPhysics对象,应用不同的显示效果,如当滑动到边界时,继续拖动的话,在iOS上会出现弹性效果,而在Android上会出现微光效果。 - 如果你想在所有平台下使用同一种效果,可以显式指定,
Flutter SDK中包含了两个ScrollPhysics的子类可以直接使用:ClampingScrollPhysics:安卓下微光效果。BouncingScrollPhysics:iOS下弹性效果。
controller
- 此属性接受一个
ScrollController对象 ScrollController的主要作用是控制滚动位置和监听滚动事件。- 默认情况下,
widget中会有一个默认的PrimaryScrollController,如果子widget中的可滚动widget没有显式的指定controller并且primary属性值为true时(默认就为true),可滚动widget会使用这个默认的PrimaryScrollController - 这种机制带来的好处是父
widget可以控制子树中可滚动widget的滚动,例如,Scaffold使用这种机制在iOS中实现了"回到顶部"的手势
代码示例
class ScrollView extends StatelessWidget {
@override
Widget build(BuildContext context) {
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return Scrollbar(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
reverse: true,
padding: EdgeInsets.all(0.0),
physics: BouncingScrollPhysics(),
child: Center(
child: Column(
//动态创建一个List<Widget>
children: str.split("")
//每一个字母都用一个Text显示,字体为原来的两倍
.map((c) => Text(c, textScaleFactor: 2.0))
.toList(),
),
),
),
);
}
}
ListView
ListView是最常用的可滚动widget,它可以沿一个方向线性排布所有子widget, 类似于ReactNative中的ListViewListView共有四种构造函数ListView()默认构造函数ListView.builder()ListView.separated()ListView custom()
ListView({
// 公共参数上面都介绍过了
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
EdgeInsetsGeometry padding,
// 是否根据子widget的总长度来设置ListView的长度,默认值为false
bool shrinkWrap = false,
// cell高度
this.itemExtent,
// 子widget是否包裹在AutomaticKeepAlive中
bool addAutomaticKeepAlives = true,
// 子widget是否包裹在RepaintBoundary中
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
// 设置预加载的区域, moren 0.0
double cacheExtent,
//子widget列表
List<Widget> children = const <Widget>[],
// 子widget的个数
int semanticChildCount,
})
属性介绍
shrinkWrap
- 表示是否根据子
widget的总长度来设置ListView的长度,默认值为false。 - 默认情况下,
ListView的会在滚动方向尽可能多的占用空间 - 当
ListView在一个无边界(滚动方向上)的容器中时,shrinkWrap必须为true
itemExtent
- 该参数如果不为
null,则会强制children的"长度"为itemExtent的值 - 这里的"长度"是指滚动方向上子
widget的长度,即如果滚动方向是垂直方向,则代表子widget的高度,如果滚动方向为水平方向,则代表子widget的长度 - 在
ListView中,指定itemExtent比让子widget自己决定自身长度会更高效,这是因为指定itemExtent后,滚动系统可以提前知道列表的长度,而不是总是动态去计算,尤其是在滚动位置频繁变化时
addAutomaticKeepAlives
- 表示是否将列表项包裹在
AutomaticKeepAlive中 - 在一个懒加载列表中,如果将列表项包裹在
AutomaticKeepAlive中,在该列表项滑出视口时该列表项不会被GC,它会使用KeepAliveNotification来保存其状态 - 如果列表项自己维护其
KeepAlive状态,那么此参数必须置为false
addRepaintBoundaries
- 性表示是否将列表项包裹在
RepaintBoundary中 - 当可滚动
widget滚动时,将列表项包裹在RepaintBoundary中可以避免列表项重绘,但是当列表项重绘的开销非常小(如一个颜色块,或者一个较短的文本)时,不添加RepaintBoundary反而会更高效 - 和
addAutomaticKeepAlive一样,如果列表项自己维护其KeepAlive状态,那么此参数必须置为false
使用示例
class ScrollView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView(
itemExtent: 60,
cacheExtent: 100,
addAutomaticKeepAlives: false,
children: renderCell(),
);
}
List<Widge
Flutter常用可滚动Widget介绍

最低0.47元/天 解锁文章
2123

被折叠的 条评论
为什么被折叠?



