Flutter 3.13 组件更新 | 欢迎 Slivers 体系 5 位新成员


theme: cyanosis

1. 介绍一下 5 个新的 Sliver 组件

在 Flutter 3.13 更新中,增加了 5 位新的 Sliver 相关组件,用于滑动视口中,完成特定功能。这篇文章将介绍一下它们的作用和使用场景。

| 组件名 | 中文名 | 介绍 | --- | --- | --- | | SliverMainAxisGroup |主轴分组滑片 | 可以容纳多个 Sliver 组件,在主轴方向上分组 | | DecoratedSliver | 装饰滑片 | 对 Sliver 进行装饰 | | SliverConstrainedCrossAxis | 交叉轴约束滑片 | 交叉轴方向上固定某个 Sliver的尺寸 | | SliverCrossAxisExpanded | 交叉轴延展滑片 | 交叉轴方向上设置某个 Sliver的尺寸占比 | | SliverCrossAxisGroup | 交叉轴分组滑片 | 可以容纳多个 Sliver 组件,在交叉轴方向上分组 |

这五个组件的使用案例,将在后续加入到开源项目 FlutterUnit 中,欢迎大家对项目的关注和支持 ~


2. 主轴滑片分组: SliverMainAxisGroup 组件

《Flutter 滑动探索 - 珠联璧合#第九章》 介绍过一个分组的滑动效果,当时使用了 flutterstickyheader 三方库来实现的。现在官方提供了 SliverMainAxisGroup 组件,就可以很轻松地完成滑片分组的效果。

具体使用场景是: 比如下面是 QQ 中分组列表滑动效果,组名下有若干成员,组的标题在滑动中会进行吸附,而且在滑动到下一组标题时,上一标题会被滑出;同样,下滑时展现也是如此。

| 上滑效果 | 下滑效果 | | ------------------------------------------------------------ | ------------------------------------------------------------ | | | |

下面,我们将基于 SliverMainAxisGroup 组件实现下面效果:

| 上滑效果 | 下滑效果 | | --- | --- | |170.gif | 171.gif |


首先准备一下数据,作为界面的填充内容:

```dart class ItemData { final String groupName; final List users;

ItemData({required this.groupName, this.users = const []});

static List get testData => [ ItemData(groupName: '幻将术士', users: ['梦小梦', '梦千']), ItemData( groupName: '幻将剑客', users: ['捷特', '龙少', '莫向阳', '何解连', '浪封', '梦飞烟']), ItemData(groupName: '幻将弓者', users: ['巫缨', '巫妻孋', '摄王', '裔王', '梦童']), ItemData( groupName: '其他', users: List.generate(20, (index) => '小兵$index')), ]; } ```

然后在组件中通过数据,映射出 SliverMainAxisGroup 列表,每个 SliverMainAxisGroup 列表中可以容纳若干个 Sliver 滑块,只要让标题通过 SliverPersistentHeader 吸顶即可:

```dart class MyHomePage extends StatelessWidget{ const MyHomePage({super.key});

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('SliverMainAxisGroup')), body: CustomScrollView( slivers: ItemData.testData.map(_buildGroup).toList(), ), ); }

Widget buildGroup(ItemData itemData) { return SliverMainAxisGroup(slivers: [ SliverPersistentHeader( pinned: true, delegate: HeaderDelegate(itemData.groupName), ), SliverList( delegate: SliverChildBuilderDelegate( (, index) => _buildItemByUser(itemData.users[index]), childCount: itemData.users.length, ), ), ]); }

Widget _buildItemByUser(String user) { return Container( alignment: Alignment.center, height: 56, child: Row( children: [ Padding( padding: const EdgeInsets.only(left: 20, right: 10.0), child: FlutterLogo(size: 30), ), Text( user, style: const TextStyle(fontSize: 16), ), ], ), ); } } ```

下面是吸顶标题的代理类,这样一共不到百行代码,就实现了分组滑动的效果,可以说是很方便的。

```dart class HeaderDelegate extends SliverPersistentHeaderDelegate { const HeaderDelegate(this.title);

final String title;

@override Widget build( BuildContext context, double shrinkOffset, bool overlapsContent) { return Container( alignment: Alignment.centerLeft, color: const Color(0xffF6F6F6), padding: const EdgeInsets.only(left: 20), height: 40, child: Text(title)); }

@override double get maxExtent => minExtent;

@override double get minExtent => 40;

@override bool shouldRebuild(covariant HeaderDelegate oldDelegate) => title!=oldDelegate.title; } ```


3. 交叉轴分组相关 Sliver 组件

其中 SliverConstrainedCrossAxisSliverCrossAxisExpanded 用于控制滑片在交叉轴的尺寸;有人可能会疑惑,一般来说,交叉轴方向的尺寸不就是视口尺寸吗,为什么需要控制交叉轴方向的滑片尺寸呢?有些场景下,我们期望交叉轴方向可以排若干个 Sliver 滑块,共同响应滚动,特别是像宽度充裕的桌面端。

如下所示,左中右三块 SliverList 水平排布,共同滑动。这种场景在之前是很难实现的,现在有了 SliverCrossAxisGroup 组件,就可以在竖直滑动视口中,将若干个 Sliver 水平排列,作为一个滑片组。而 SliverConstrainedCrossAxisSliverCrossAxisExpanded 两个组件就是用于控制滑片在交叉轴方向尺寸的,所以说这三位是同一条船上的。

| 下滑 | 上滑 | | --- | --- | | 168.gif | 169.gif |

SliverConstrainedCrossAxis 组件可以在交叉轴方向容纳若干个 Sliver 组件。比如竖直方向滑动中,他就类似于 Row 组件,将 Sliver 孩子们水平排列。其中:

SliverConstrainedCrossAxis:指定滑片的交叉轴尺寸。
SliverCrossAxisExpanded:指定滑片的交叉轴上占据的份额。

案例中需要准备三个 SliverList 的滑块,为了简单起见,这里简单封装一个 SliverColorList 用于构建滑块组件,可指定色块颜色、条目高、条目数量等:

```dart class SliverColorList extends StatelessWidget { final double height; final double fontSize; final Color? color1; final Color? color2; final int count; const SliverColorList( {super.key, required this.height, required this.fontSize, required this.count, this.color1, this.color2});

@override Widget build(BuildContext context) { return SliverList.builder( itemBuilder: (BuildContext context, int index) { return Container( color: index.isEven ? color1 : color2, height: height, child: Center( child: Text( 'Item ${index}', style: TextStyle(fontSize: fontSize), ), ), ); }, itemCount: count, ); } } ```


下面就是 SliverCrossAxisGroup 的使用方式,其实很简单,塞入 slivers 列表就行了。其中通过 SliverConstrainedCrossAxis 可以指定某个滑块在水平方向的固定尺寸;也可以通过 SliverCrossAxisExpanded 指定在水平方向尺寸的占份,下面 tag1 和 tag2 处通过 flex 属性指定份额 1:2, 所以右侧滑块的水平尺寸是中间的两倍:

```dart class SliverCrossAxisGroupExample extends StatelessWidget { const SliverCrossAxisGroupExample({super.key});

@override Widget build(BuildContext context) { return CustomScrollView( slivers: [ SliverCrossAxisGroup( slivers: [ SliverConstrainedCrossAxis( maxExtent: 100, sliver: SliverColorList( height: 100.0, fontSize: 24, count: 8, color1: Colors.amber[300], color2: Colors.blue[300], ), ), SliverCrossAxisExpanded( flex: 1, // tag1 sliver: SliverColorList( height: 80.0, fontSize: 18, count: 15, color1: Colors.green[300], color2: Colors.red[300], ), ), SliverCrossAxisExpanded( flex: 2, // tag2 sliver: SliverColorList( height: 50.0, fontSize: 20, count: 6, color1: Colors.purple[300], color2: Colors.orange[300], )), ], ), ], ); } } ```

这就是 SliverCrossAxisGroup、SliverConstrainedCrossAxis、SliverCrossAxisExpanded 三个组件的所有用法,还是非常简单和直观的。解决的场景是:

在交叉轴方向,需要摆放若干个滑块时,这些滑块可以共同滚动。


4. 装饰滑块 DecoratedSliver

DecoratedSliver 其实很好理解,它就是滑动版的 DecoratedBox, 可以在滑动视口中,用于装饰 Sliver 滑片。之前需要对滑片进行装饰,是很难做到的,因为滑块在布局上受到的是滑动约束 SliverConstraints ,而不是盒约束 BoxConstraints。现在有了 DecoratedSliver 组件,指定 decoration 装饰对象即可:

image.png

其中 decoration 参数类型是 Decoration ,可以使用 BoxDecoration 实现类,添加阴影、边线、圆角、渐变、颜色、图片背景等。 当然也可以自定义 Decoration 自己绘制,装饰的详细使用可详见 《 【Flutter 组件集录】 DecoratedBox》 ,这里就不赘述了。

| 标题 | | | --- | --- | | 401a84b0a0d4f22125573d3256ebfd2.jpg | cb572c92cb1b216cc6c5c2c6506a5ee.jpg |

SliverPadding( padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8), sliver: DecoratedSliver( decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: Color(0xFF111133), blurRadius: 2, offset: Offset(-2, -1)) ], gradient: LinearGradient( colors: <Color>[ Color(0xFFEEEEEE), Color(0xFF111133), ], stops: <double>[0.1, 1.0], ), ), sliver: SliverList( delegate: SliverChildBuilderDelegate( (_, index) => Padding( padding: const EdgeInsets.all(8.0), child: Center( child: Text( '张风捷特烈-$index', style: TextStyle(fontSize: 24, color: Colors.white), )), ), childCount: 128), ), ), ),

到这里,五个新的 Sliver 组件就介绍完毕了,总的来说这五个都是非常有用,而且使用起来并不复杂。可以解决一些特定的滑动问题。本文的组件使用案例将会集成到 FlutterUnit 中,欢迎大家对项目多多关照。那本文就到这里,谢谢观看~


尾声:

笔者将在 bilibli 不定期发布一些视频教程,欢迎大家可以关注和支持。另外公众号也可以关注一下,也会发布一些文章。

bilibli 账号: 张风捷特烈
公众号: 编程之王

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值