当前位置:   article > 正文

Flutter教程09——可滚动组件_flutter 滚动条

flutter 滚动条

目录

 

1.可滚动组件介绍

1.1Scrollable

1.2Viewport

1.3Sliver

2.1Scrollbar

2.SingleChildScrollView

3.ListView

3.1ListView.builder

3.2ListView.separated


1.可滚动组件介绍

Flutter中有两种布局模型:Render的盒模型布局和Sliver按需加载列表布局。

可滚动的组件的子组件一般会很多,如果一次性全部加载会影响性能。为此Flutter提供了Sliver(片段),Sliver可以包含多个子组件。Sliver作用:按需加载子组件并确定每一个子组件的布局。

Flutter中可滚动主要由三部分组成:

Scrollable,用于处理滑动手势,确定滑动偏移,滑动时构建Viewport;

Viewport,显示的视窗,即列表的可视区域;

Sliver,视窗里显示的元素;

布局过程:

Scrollable,监听到用户滑动后,根据滑动偏移构建Viewport;

Viewport将当前视口信息和配置信息通过SliverConstraints传递给Sliver;

Sliver中对子组件按需进行构建和布局;

1.1Scrollable

用来处理滑动,确定偏移量,在滑动时构建Viewport。

  1. Scrollable({
  2. ...
  3. this.axisDirection = AxisDirection.down,
  4. this.controller,
  5. this.physics,
  6. required this.viewportBuilder, //后面介绍
  7. })

axisDirection,滚动方向;

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

physics,此属性接受一个ScrollPhysics类型的对象,决定可滚动组件如何响应用户操作;

viewportBuilder,构建 Viewport 的回调; 

1.2Viewport

用于渲染当前视口中需要显示 Sliver。

  1. Viewport({
  2. Key? key,
  3. this.axisDirection = AxisDirection.down,
  4. this.crossAxisDirection,
  5. this.anchor = 0.0,
  6. required ViewportOffset offset, // 用户的滚动偏移
  7. // 类型为Key,表示从什么地方开始绘制,默认是第一个元素
  8. this.center,
  9. this.cacheExtent, // 预渲染区域
  10. //该参数用于配合解释cacheExtent的含义,也可以为主轴长度的乘数
  11. this.cacheExtentStyle = CacheExtentStyle.pixel,
  12. this.clipBehavior = Clip.hardEdge,
  13. List<Widget> slivers = const <Widget>[], // 需要显示的 Sliver 列表
  14. })

1.3Sliver

作用是对子组件进行构建和布局

2.1Scrollbar

Scrollbar是一个Material风格的滚动指示器(滚动条),如果要给可滚动组件添加滚动条,只需将Scrollbar作为可滚动组件的任意一个父级组件即可。

2.SingleChildScrollView

SingleChildScrollView类似于Android中的ScrollView,它只能接收一个子组件:

  1. SingleChildScrollView({
  2. this.scrollDirection = Axis.vertical, //滚动方向,默认是垂直方向
  3. this.reverse = false,
  4. this.padding,
  5. bool primary,
  6. this.physics,
  7. this.controller,
  8. this.child,
  9. })

primary,表示是否使用 widget 树中默认的PrimaryScrollController;当滑动方向为垂直方向(scrollDirection值为Axis.vertical)并且没有指定controller时,primary默认为true。

SingleChildScrollView不支持基于 Sliver 的延迟加载模型,所以如果超出屏幕的内容太多性能会很差,此时应该使用支持Sliver延迟加载的可滚动组件如ListView。 

  1. String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  2. return Scrollbar(
  3. child: SingleChildScrollView(
  4. child: Center(
  5. child: Column(
  6. children: str
  7. .split('')
  8. .map(
  9. (item) => Text(
  10. item,
  11. textScaleFactor: 2,
  12. ),
  13. )
  14. .toList(),
  15. ),
  16. ),
  17. ),
  18. );

效果:

 

3.ListView

可以沿一个方向线性排布所有子组件,也支持列表项懒加载。

  1. ListView({
  2. ...
  3. //可滚动widget公共参数
  4. Axis scrollDirection = Axis.vertical,
  5. bool reverse = false,
  6. ScrollController? controller,
  7. bool? primary,
  8. ScrollPhysics? physics,
  9. EdgeInsetsGeometry? padding,
  10. //ListView各个构造函数的共同参数
  11. double? itemExtent,
  12. Widget? prototypeItem, //列表项原型,后面解释
  13. bool shrinkWrap = false,
  14. bool addAutomaticKeepAlives = true,
  15. bool addRepaintBoundaries = true,
  16. double? cacheExtent, // 预渲染区域长度
  17. //子widget列表
  18. List<Widget> children = const <Widget>[],
  19. })

 itemExtent,如果不为null则会强制children的“长度”为itemExtent的值,此处的长度指的是滚动方向上组件的长度。指定itemExtent让子组件自身决定自身长度会有更好的性能,因为指定后滚动系统可以提前知道列表长度;

prototypeItem,如果知道列表项长度相同但不知道具体多少,可以指定一个列表项,指定后滚动组件会在layout时计算一次主轴方向的长度,会有更好的性能;

shrinkWrap,表示是否根据子组件的总长度来设置ListView的长度,默认为false;

children,接受一个List<Widget>,该方式只适合子组件数量较少时,反之应该使用ListView.builder来动态构建;

  1. return Scrollbar(
  2. child: ListView(
  3. shrinkWrap: true,
  4. padding: const EdgeInsets.all(20),
  5. children: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  6. .split('')
  7. .map(
  8. (item) => Text(
  9. item,
  10. textScaleFactor: 2,
  11. ),
  12. )
  13. .toList(),
  14. ),
  15. );

3.1ListView.builder

适合列表项比较多或者列表项不确定的情况。

  1. ListView.builder({
  2. // ListView公共参数已省略
  3. ...
  4. required IndexedWidgetBuilder itemBuilder,
  5. int itemCount,
  6. ...
  7. })

itemBuilder,列表项的构建器,类型为IndexedWidgetBuilder,返回值为一个widget;当列表滚动到具体的index位置时,会调用该构建器构建列表项;

itemCount,列表项的数量,如果为null,则为无限列表;

3.2ListView.separated

可以在生成的列表项之间添加一个分割组件,separatorBuilder参数,该参数是一个分割组件生成器。

  1. child: ListView.separated(
  2. itemCount: 100,
  3. itemBuilder: (BuildContext context, int index) {
  4. return ListTile(title: Text('$index'));
  5. },
  6. separatorBuilder: (BuildContext context, int index) {
  7. return const Divider(
  8. color: Colors.black26,
  9. );
  10. },
  11. ),

效果:

4. 滚动监听和控制

4.1ScrollController

  1. ScrollController({
  2. double initialScrollOffset = 0.0, //初始滚动位置
  3. this.keepScrollOffset = true,//是否保存滚动位置
  4. ...
  5. })

 滚动监听

ScrollController间接继承自Listenable,我们可以根据ScrollController来监听滚动事件:

controller.addListener(()=>print(controller.offset))

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号