Flutter学习总结(十五、Flutter列表)

Flutter列表

一起从0开始学习Flutter!

基本上的组件学的差不多了,我们开始一起来学习日常用的最多的列表功能。列表我们一般常用的有ScrollView,ListView,和GridView,在Flutter中也是有一一对应的组件,在Flutter里ScrollView是抽象类无法直接被实例化,我们可以使用它的子类,如NestedScrollView,BoxScrollView,在Flutter比较特殊ListView,GridView也是ScrollView的子类。我们依次看下。

1.NestedScrollView

这里的NestedScrollView跟Android中的意义不一样,在Android中是直接一个可以滑动的列表,我们将子View放到ScrollView下的ViewGroup中就可以实现一个页面的滚动,而这里的NestedScrollView是做了一个包含TabBar的一个封装,我们可以利用它轻松的实现向上滑动的时候顶部的折叠。

const NestedScrollView({
    Key key,
    this.controller,//滚动操作的控制器,给我们一个默认值_NestedScrollController,如果需要修改可以模仿来做更改
    this.scrollDirection = Axis.vertical, //滚动的方向,Axis.vertical竖向滚动,horizontal横向滚动
    this.reverse = false,//是否页面做翻转,如果是True则bar在下面,滚动的在上面
    this.physics,//当用户停止滑动,滑动到顶部时的动作
    @required this.headerSliverBuilder,//参照下面的详细说明
    @required this.body,//参照下面的详细说明
    this.dragStartBehavior = DragStartBehavior.start,//拖拽开始的状态
  })

headerSliverBuilder
向上滑动的时候的折叠区域,可以传入一组的控件 List,如果我们在向上滑动的时候可以折叠的话我们需要返回一个SliverOverlapAbsorber,SliverOverlapAbsorber稍后我们做详细解释。
body
传入一个可以滑动的布局,比如我们可以传入一个CustomScrollView,我们则可以通过CustomScrollView来实现页面的滑动,也可以传入SliverList,SliverGrid让页面滚动起来。
先来看下上面提到的SliverOverlapAbsorber。

2.SliverOverlapAbsorber

使用SliverOverlapAbsorber包裹SliverAppBar让在滑动的时候可以进行通知头部,控制AppBar的收放。还是先看下构造函数:

const SliverOverlapAbsorber({
    Key key,
    @required this.handle, //参照下面的详细说明
    Widget child,//需要控制的组件,一般使用SliverAppBar
  })

handle
作为一个必选参数来控制堆叠时的控件高度,我们一般使用下面NestedScrollView.sliverOverlapAbsorberHandleFor来创建一个默认的操作。

handle:NestedScrollView.sliverOverlapAbsorberHandleFor(context)

3.SliverAppBar

跟AppBar有很多共通的参数,我们可以拿出来它与AppBar的不同之处来作解释:

const SliverAppBar({
    Key key,
    this.flexibleSpace,//我们需要显示的标题栏里的内容,可以根据需要进行自己的设置,比如一个Text
    this.forceElevated = false,//是否保留SliverAppBar下面的阴影,True不管是滚动还是停止都有阴影,False则都不显示
    this.expandedHeight,//标题栏和文字说明直接的间距
    this.floating = false,//和snap配合使用
    this.pinned = false,//顶部的Title栏是否是固定的,False则不显示title栏,True则会滑动时保留title栏
    this.snap = false,//和floating配合使用,两个都是True则滑动到顶再下向滑动时首先是标题栏先滑下来,然后再是列表的向下滚动。
    this.stretch = false,//是否拉伸以充满滑动区域,没有试出来它的效果
    this.stretchTriggerOffset = 100.0,//设定调用onStretchTrigger的滑动距离
    this.onStretchTrigger,//设定的回调
    ...
  })

设置还是比较简单,可以根据我们是否需要滚动,是否滚动的时候是否固定头部来进行设置。

4.ListView

作为一个线性排布所有子控件的容器,它其实比较像在Android中认识的ScrollView,但是我们可以通过itemBuilder来实现Android中的ListView的形式。先看下ListView的构造方法,先省略NestedScrollView里面共通的参数:

ListView({
    Key key,
    bool shrinkWrap = false,//是否根据子组件的总长度来设置ScrollView的长度,如果ScrollView的父容器是一个无边际的的容器则设置为True。
    EdgeInsetsGeometry padding,//设置ListView的内填充大小
    this.itemExtent,//如果不为空则会强制children的长度为itemExtent的值。
    bool addAutomaticKeepAlives = true,//是否将列表项放到AutomaticKeepAlive组件中,在懒加载的时候如果设置为True则滑出窗口视图的时候不会被回收,由KeepAliveNotification来保存状态
    bool addRepaintBoundaries = true,//是否将列表项放到RepaintBoundary组件中,设置为True在列表滚动的时候可以避免重绘,但是如果每个Item都很简单比较小的时候如果设置为True会更高效。
    bool addSemanticIndexes = true,//设置是否将列表项添加到用位置来表示的语义控件中,还是原来说到的辅助功能使用的
    double cacheExtent,//缓存的长度
    List<Widget> children = const <Widget>[],//参照下面的详细说明
    int semanticChildCount,//语义表达的列表项的数量,还是辅助功能使用。
    ...
  })

children
这里用来存放滑动的内容,我们可以创建一组Text为了测试滑动比如:

ListView(
          children: <Widget>[
            Text("Hello"),
            Text("Hello"),
            Text("Hello"),
            Text("Hello"),
          ],
        )

如果要是显示一组内容相同的列表我们可以使用ListView的建造者模式的方法ListView.builder(),其他的参数同ListView只是多了一个

 @required IndexedWidgetBuilder itemBuilder,

我们可以通过它来创建一组数据的列表比如:

ListView.builder(
          itemBuilder: (BuildContext context, int index) {
            return Text("Hello" + index.toString());
          },
          padding: EdgeInsets.all(30),
        )

常用的还有ListView.separated()只是比ListView.builder()多了一个分割线的设置,不再赘述,可以自己试一下。

5.GridView

跟ListView的参数有很大的相似度,它的功能就是将竖向列表在横向也可以按照指定的块数显示。我们看下它的构造方法,跟ListView类似的不再说明:

GridView({
    Key key,
    @required this.gridDelegate,//参照下面的详细说明
   ...
  })

gridDelegate
我们看到需要传入一个SliverGridDelegate,但是该类是一个抽象类,我们需要传入一个实现类,找到了SliverGridDelegateWithFixedCrossAxisCount,我们将其传入,来看下它有哪些参数

const SliverGridDelegateWithFixedCrossAxisCount({
    @required this.crossAxisCount,//要划分的块数
    this.mainAxisSpacing = 0.0,//跟主要滑动方向一致的每块间隔大小
    this.crossAxisSpacing = 0.0,//另外一个方向上每块间隔大小
    this.childAspectRatio = 1.0,//滑动方向和另一方向块的大小比例
  })

一个简单的使用:

GridView(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount:3,
              mainAxisSpacing:10,
            crossAxisSpacing: 10,
          ),
          children: <Widget>[
            Text("Hello",style: TextStyle(backgroundColor: Colors.green),),
            Text("Hello"),
            Text("Hello"),
            Text("Hello"),
          ],
        ),

在GridView中也有builder()和separated()方法,跟ListView的方法一致。

6.SliverList

可以理解为我们可以将多个布局按照一个顺序来进行的排列,每个都是单独的个体。它的构造比较简单,我们看下:

const SliverList({
    Key key,
    @required SliverChildDelegate delegate,//参照下面的详细说明
  })

delegate
就只需要传入一个代理,SliverChildDelegate是一个抽象类,我们还需要找到它的实现SliverChildListDelegate,来看下SliverChildListDelegate的构造:

SliverChildListDelegate(
    this.children, {
    this.addAutomaticKeepAlives = true,
    this.addRepaintBoundaries = true,
    this.addSemanticIndexes = true,
    this.semanticIndexCallback = _kDefaultSemanticIndexCallback,
    this.semanticIndexOffset = 0,
  })

跟List基本上一样的参数,只是children是一组组件,我们需要一个个的实现,SliverChildDelegate下面还有一个实现是SliverChildBuilderDelegate,这个可以帮助我们快速的创建一组列表与ListView相同的略过:

const SliverChildBuilderDelegate(
    this.builder, //这里创建了一个构造器,下面详细说明
	{this.findChildIndexCallback,//构造一个返回当前Item的Index的方法
    this.childCount,//想要显示的Item的数量
    ...
  })

builder
可以看到它的定义是比较有意思的,是定义了一个方法:

typedef IndexedWidgetBuilder = Widget Function(BuildContext context, int index);

我们需要传一个函数进去,可以简单的试一下:

delegate: SliverChildBuilderDelegate(
                        (BuildContext context, int index) {
                      return Container(
                        alignment: Alignment.center,
                        color: Colors.red,
                        child: Text("position is $index",style: TextStyle(fontSize: 14,color: Colors.black),),
                      );
                    }
                )

这样就构造了一个我想要显示的每一个条目的样式,然后控制数量和缓存机制就可以了。

7.SliverGrid

跟GridView是一样的显示形式,只是也是进行了分块,我们还是看下构造方法:

  const SliverGrid({
    Key key,
    @required SliverChildDelegate delegate,
    @required this.gridDelegate,
  })

只是比上面的SliverList多了一个gridDelegate,我们只看下gridDelegate,看到它需要传入SliverGridDelegate,但是也是一个抽象类,还是看下它的实现SliverGridDelegateWithFixedCrossAxisCount,嗯,是的,跟GridView中的是一样的,我们可以直接去看GridView中的说明。这样进行设置后一个可以分割的Grid就完成了。

8.CustomScrollView

跟ScrollView也不是一样的,它比较像是一个粘合剂的作用,如果我们的列表显示多个列表的组合那么可以放置到CustomScrollView里面,来保证它们的滑动事件的统一,里面也可以放置像ListView和GridView这样子的组件,但是需要注意如果我们需要让他们联合滚动需要不能使用ListView和GridView,我们需要一种已经帮我们做好分割的SliverList和SliverGrid,还是先看下他的构造方法,有部分同NestedScrollView直接去掉了:

const CustomScrollView({
    Key key,
    bool primary,//如果为True则会让它的Controller创建一个PrimaryScrollController的实体,不能再自定义Controller。
    bool shrinkWrap = false,//是否根据子组件的总长度来设置ScrollView的长度,如果ScrollView的父容器是一个无边际的的容器则设置为True。
    Key center,
    this.slivers = const <Widget>[],//参照下面的详细说明
    ...
  })

slivers
这里我们就要放入可分裂的组件了,我们可以将上面的SliverList或者SliverGrid放入其中,可以混合放入,这样就成了一个混合列表。
滚动页面的内容比较复杂,不是很好理解,还是建议多去试一试,这样可以加深我们的记忆。

接下来我们一起来学习Flutter中的页面跳转

你可能感兴趣的:(Flutter)