下面我们来介绍下Flutter中的滑动控件SingleChildScrollView、列表ListView和表格GridView。
SingleChildScrollView
SingleChildScrollView类似于Android中的ScrollView,我使用的较浅,在我目前看来,他和ScrollView的唯一区别就是它还可以横向滚动。
我们先来看下他的定义:
| |
scrollDirection:设定滚动的方向,可以设定Axis.vertical或者Axis.horizon;reverse:是否按照阅读方向的反方向滑动,emmm这个可能有点觉得莫名其妙,但是如阿拉伯语言地区,他们阅读和我国古时候一样是从右向左的,所以如果reverse为true,且滚动方向是水平滚动的话,如果系统时阿拉伯语等从右向左阅读的语言时,方向是从右向左的;padding:留白的大小,和Padding的用法一样,通过EdgeInsets来设定,具体可以看前几章将Flutter基础Widget;primary:指是否使用widget树中默认的PrimaryScrollController;当滑动方向为垂直方向(scrollDirection值为Axis.vertical)并且没有指定controller时,primary默认为true;physics:用于控制滚动方式,这个等会重点讲解;controller:用于滚动监听及控制;child:子Widget。
physics
这个参数是用于控制滚动方式,有几种参数:
NeverScrollablePhysics:呈现不可滚动状态;BouncingScrollPhysics:当列表滑动结束时,会回弹列表,类似于iOS的列表滑动效果;
ClampingScrollPhysics:滑动结束时会显示水波纹阴影,类似于Android的列表滑动效果;
FixedExtentScrollPhysics:可以自己制作滑动效果,但是我也不会,所以在此不做解释😝。
ListView
ListView可以沿一个方向上线性排布所有子组件(不仅局限于竖直方向)。
让我们来看下他的定义:
| |
公共属性我们就不讲了,上面SingleChildScrollView已经讲过了,我们现在只讲他特有的:
itemExtent:用于控制ListView的长度,如果不为null,则强制所有子Widget合起来的长度小于设定的值:如果ListView是横向的,则所有子Widget横向长度的和小于它;如果ListView是纵向的,则所有子Widget纵向长度的和小于它;shrinkWrap:该属性表示是否根据子组件的总长度来设置ListView的长度,默认值为false。默认情况下,ListView的会在滚动方向尽可能多的占用空间。当ListView在一个无边界(滚动方向上)的容器中时,shrinkWrap必须为true;addAutomaticKeepAlives:该属性表示是否将列表项(子组件)包裹在AutomaticKeepAlive组件中;典型地,在一个懒加载列表中,如果将列表项包裹在AutomaticKeepAlive中,在该列表项滑出视口时它也不会被GC(垃圾回收),它会使用KeepAliveNotification来保存其状态。如果列表项自己维护其KeepAlive状态,那么此参数必须置为false;addRepaintBoundaries:该属性表示是否将列表项(子组件)包裹在RepaintBoundary组件中。当可滚动组件滚动时,将列表项包裹在RepaintBoundary中可以避免列表项重绘,但是当列表项重绘的开销非常小(如一个颜色块,或者一个较短的文本)时,不添加RepaintBoundary反而会更高效。和addAutomaticKeepAlive一样,如果列表项自己维护其KeepAlive状态,那么此参数必须置为false;cacheExtent:设定缓存大小。
默认情况下一个一个设定children很麻烦,所以为了方便,Flutter还提供了一个builder构造方法:
ListView.builder
| |
itemCount:是需要加载子Widget的长度;itemBuilder:列表项的构造器,当列表滚动到具体的index位置时,会调用该构建器构建列表项。
看例子:
| |

ListView.separated
用于添加分割线。相较于ListView.builder多了一个separatorBuilder参数,该参数是一个分割组件生成器。
下面我们看一个例子:奇数行添加一条蓝色下划线,偶数行添加一条绿色下划线。
| |

GridView
GridView可以构造一个网格列表,定义如下:
| |
大部分参数和ListView都相同,我们只关注gridDelegate这个参数:
gridDelegate作用是控制GridView子组件如何排列,Flutter中提供了两个类SliverGridDelegateWithFixedCrossAxisCount和SliverGridDelegateWithMaxCrossAxisExtent,我们可以直接使用,下面我们分别来介绍一下它们。
SliverGridDelegateWithFixedCrossAxisCount
该子类实现了一个横轴为固定数量子元素的layout算法,其构造函数为:
| |
crossAxisCount:横轴子元素的数量。此属性值确定后子元素在横轴的长度就确定了,即ViewPort横轴长度除以crossAxisCount的商。mainAxisSpacing:主轴方向的间距。crossAxisSpacing:横轴方向子元素的间距。childAspectRatio:子元素在横轴长度和主轴长度的比例。由于crossAxisCount指定后,子元素横轴长度就确定了,然后通过此参数值就可以确定子元素在主轴的长度。
SliverGridDelegateWithMaxCrossAxisExtent
该子类实现了一个横轴子元素为固定最大长度的layout算法,其构造函数为:
| |
maxCrossAxisExtent为子元素在横轴上的最大长度,之所以是“最大”长度,是因为横轴方向每个子元素的长度仍然是等分的。其它参数和SliverGridDelegateWithFixedCrossAxisCount相同。
GridView.builder
和ListView一样,当子Widget数量较多时,也提供了builder方法:
| |
这个就不在这举例了,gridDelegate和前面一样的,itemBuilder和ListView的一样的。