写点什么

flutter 系列之: 使用 SliverList 和 SliverGird

作者:程序那些事
  • 2023-02-13
    广东
  • 本文字数:3161 字

    阅读完需:约 10 分钟

简介

在上一篇文章我们讲解 SliverAppBar 的时候有提到过,Sliver 的组件一般都用在 CustomScrollView 中。除了 SliverAppBar 之外,我们还可以为 CustomScrollView 添加 List 或者 Grid 来实现更加复杂的组合效果。


今天要向大家介绍的就是 SliverList 和 SliverGird。

SliverList 和 SliverGird 详解

从名字就可以看出 SliverList 和 SliverGird 分别是 List 和 Grid 的一种,他们和 List 与 Grid 最大的区别在于,他们可以控制子 widget 在 main axis 和 cross axis 之间的间隔,并且可以通过 Extent 属性来控制子 widget 的大小,非常的强大。


我们先来看下这两个组件的定义和构造函数:


class SliverList extends SliverMultiBoxAdaptorWidget {  /// Creates a sliver that places box children in a linear array.  const SliverList({    Key? key,    required SliverChildDelegate delegate,  }) : super(key: key, delegate: delegate);
复制代码


SliverList 继承自 SliverMultiBoxAdaptorWidget,它的构造函数比较简单,需要传入一个 SliverChildDelegate 的参数,这里的 SliverChildDelegate 使用的是 delegate 的方法来创建 SliverList 的子组件。


SliverChildDelegate 是一个抽象类,它有两个实现类,分别是 SliverChildBuilderDelegate 和 SliverChildListDelegate。


其中 SliverChildBuilderDelegate 是用的 builder 模式来生成子 widget,在上一篇文章中,我们构建 SliverList 就是使用的这个 builder 类。


SliverChildBuilderDelegate 使用 builder 来生成子 Widget,而 SliverChildListDelegate 需要传入一个 childList 来完成构造,也就是说 SliverChildListDelegate 需要一个确切的 childList,而不是用 builder 来构建。


要注意的是 SliverList 并不能指定子 widget 的 extent 大小,如果你想指定 List 中的子 widget 的 extent 大小的话,那么可以使用 SliverFixedExtentList:


class SliverFixedExtentList extends SliverMultiBoxAdaptorWidget {  const SliverFixedExtentList({    Key? key,    required SliverChildDelegate delegate,    required this.itemExtent,  }) : super(key: key, delegate: delegate);
复制代码


可以看到 SliverFixedExtentList 和 SliverList 相比,多了一个 itemExtent 参数,用来控制子 widget 在 main axis 上的大小。


然后我们再来看一下 SliverGird:


class SliverGrid extends SliverMultiBoxAdaptorWidget {  /// Creates a sliver that places multiple box children in a two dimensional  /// arrangement.  const SliverGrid({    Key? key,    required SliverChildDelegate delegate,    required this.gridDelegate,  }) : super(key: key, delegate: delegate);
复制代码


SliverGrid 也是继承自 SliverMultiBoxAdaptorWidget,和 SliverList 一样,它也有一个 SliverChildDelegate 的参数,另外它还多了一个 gridDelegate 的参数用来控制 gird 的布局。


这里的 gridDelegate 是一个 SliverGridDelegate 类型的参数,用来控制 children 的 size 和 position。


SliverGridDelegate 也是一个抽象类,它有两个实现类,分别是 SliverGridDelegateWithMaxCrossAxisExtent 和 SliverGridDelegateWithFixedCrossAxisCount,这两个实现类的区别就在于 MaxCrossAxisExtent 和 FixedCrossAxisCount 的区别。


怎么理解 MaxCrossAxisExtent 呢?比如说这个 Grid 是竖向的,然后 Gird 的宽度是 500.0,如果 MaxCrossAxisExtent=100,那么 delegate 将会创建 5 个 column,每个 column 的宽度是 100。


crossAxisCount 则是直接指定 cross axis 的 child 个数有多少。

SliverList 和 SliverGird 的使用

有了上面介绍的 SliverList 和 SliverGird 的构造函数,接下来我们具体来看下如何在项目中使用 SliverList 和 SliverGird。


默认情况下 SliverList 和 SliverGird 是需要和 CustomScrollView 一起使用的,所以我们先创建一个 CustomScrollView,在它的 slivers 属性中,放入一个 SliverAppBar 组件:


CustomScrollView(      slivers: <Widget>[        const SliverAppBar(          pinned: true,          snap: false,          floating: false,          expandedHeight: 200.0,          flexibleSpace: FlexibleSpaceBar(            title: Text('SliverList and SliverGrid'),          ),        ),      ],    );
复制代码


SliverAppBar 只是一个 AppBar,运行可以得到下面的界面:



我们还需要为它继续添加其他的 slivers 组件。


首先给他添加一个 SliverGrid:


SliverGrid(          gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(            maxCrossAxisExtent: 200.0,            mainAxisSpacing: 20.0,            crossAxisSpacing: 50.0,            childAspectRatio: 4.0,          ),          delegate: SliverChildBuilderDelegate(                (BuildContext context, int index) {              return Container(                alignment: Alignment.center,                color: Colors.green[100 * (index % 9)],                child: Text('grid item $index'),              );            },            childCount: 20,          ),        ),
复制代码


这里我们设置了 gridDelegate 属性,并且自定义了 SliverChildBuilderDelegate,用来生成 20 个 Container。


运行得到的界面如下:



然后为其添加 SliverList:


SliverList(          delegate: SliverChildBuilderDelegate(                (BuildContext context, int index) {              return Container(                color: index.isOdd ? Colors.white : Colors.green,                height: 50.0,                child: Center(                  child: ListTile(                    title: Text(                      '100' + index.toString(),                      style: const TextStyle(fontWeight: FontWeight.w500),                    ),                    leading: Icon(                      Icons.account_box,                      color: Colors.green[100 * (index % 9)],                    ),                  ),                ),              );            },            childCount: 15,          ),        ),
复制代码


因为 SliverList 只需要传入一个 delegate 参数,这里我们生成了 15 个 child 组件。生成的界面如下:



因为 SliverList 不能控制 List 中子 widget 的 extent,所以我们再添加一个 SliverFixedExtentList 看看效果:


SliverFixedExtentList(          itemExtent: 100.0,          delegate: SliverChildBuilderDelegate(                (BuildContext context, int index) {              return Container(                color: index.isOdd ? Colors.white : Colors.green,                height: 50.0,                child: Center(                  child: ListTile(                    title: Text(                      '200' + index.toString(),                      style: const TextStyle(fontWeight: FontWeight.w500),                    ),                    leading: Icon(                      Icons.account_box,                      color: Colors.green[100 * (index % 9)],                    ),                  ),                ),              );            },            childCount: 15,          ),
复制代码


SliverFixedExtentList 和 SliverList 相比多了一个 itemExtent 属性,这里我们将其设置为 100,运行可以得到下面的界面:



可以看到 List 中的子 Widget 高度发生了变化。

总结

在 CustomScrollView 中使用 SliverList 和 SliverGird,可以实现灵活的呈现效果。


本文的例子:https://github.com/ddean2009/learn-flutter.git

发布于: 2 小时前阅读数: 8
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020-06-07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
flutter系列之:使用SliverList和SliverGird_flutter_程序那些事_InfoQ写作社区