全国免费咨询:

13245491521

VR图标白色 VR图标黑色
X

中高端软件定制开发服务商

与我们取得联系

13245491521     13245491521

2024-10-16_【Flutter】Sliver的各种修饰你不会不知道吧

您的位置:首页 >> 新闻 >> 行业资讯

【Flutter】Sliver的各种修饰你不会不知道吧 点击关注公众号,“技术干货”及时达! Sliver 的各种装饰器前言最近项目确实很多,工作也很忙,更新都不给力了,(主要是晚上也要打奥杜尔啊) 大家见谅。 事情是这么回事,一朋友在开发中遇到问题请教到我这里,一顿扒扒之后我感觉他还是对 Silver 以及它对应的一些装饰器不是很熟悉导致走错了方向,遂有此文,一个是自己复习下,一方面也是给大家科普一下当做是查漏补缺了。 正文: Sliver 大家肯定都不陌生了,它是 Flutter 开发中非常常见的控件,Sliver 通常在 CustomScrollView 中使用,允许开发者灵活地组合不同类型的 Sliver 组件。 我们一般都会用到如 SliverList:用于创建一个可滚动的列表。SliverGrid:用于创建一个可滚动的网格。SliverAppBar:通常用于创建一个具有可扩展和收缩功能的应用栏。这些 Sliver ,而其中最最常见的又是 SliverList 这个控件。 相对比 ListView ,我个人更喜欢使用 SliverList ,说起 ListView 其实本质就是对 Sliver 的一种封装。ListView 提供了一个简单易用的接口,用于创建垂直滚动的列表,同时隐藏了许多底层实现的复杂性,适合大多数基本列表场景。简单理解就是场景化封装,熟悉谷歌的都知道谷歌最爱干这事了。 而我们直接使用 SliverList 就会更加的灵活,可以添加不同的组合滚动,可以设置不同的装饰器,从而到达我们想要的效果。 下面就一起看看常用的装饰器有哪些,并且实现朋友说的那个场景。 一、常见的装饰器1.1 SliverToBoxAdapterSliverToBoxAdapter 允许您在 Sliver 中插入一个普通的非 Sliver 组件。它可以用于在 CustomScrollView 中混合 Sliver 和普通 Widget。 SliverToBoxAdapter( child: Container( height: 100, color: Colors.orange, child: Center(child: Text('This is a normal widget')), ), ) 这个是最常见,最基础的装饰了,必须要把普通的 Widget 转换为 Sliver 的 Widgert,否则直接报错。 1.2 SliverFillRemainingSliverFillRemaining( child: Container( color: Colors.green, child: Center(child: Text('Filling remaining space')), ), ) 这个也是很常见的一个包装器,可以允许您填充剩余的可滚动空间。有点权重的那种意思。各种场景都比较实用,比如一些 Loading 布局,错误布局,自定义的一些效果也很常用。 1.3 SliverPaddingSliverPadding( padding: EdgeInsets.all(16.0), sliver: SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return ListTile(title: Text('Item $index')); }, childCount: 100, ), ), ) SliverPadding 是一个用于在 Sliver 组件周围添加填充的装饰器。它允许您为 Sliver 的内容设置内边距,从而控制 Sliver 与其父容器或其他 Sliver 之间的距离。 我发现很多人不知道这个装饰,比如不同的 Sliver 包装 SliverPadding ,那么它是对不同的 Sliver 生效的,不是对内部的子 Item 生效,不管是包装的一个Silver 还是一组 Sliver 都是这样。 例如一个 CustomScrollView 中我们设置不同的 Sliver 组 SliverPadding( padding: const EdgeInsets.all(10), sliver: SliverList( delegate: SliverChildListDelegate( [ Container( height: 100, color: Colors.red, child: Center(child: Text('Custom Item 1')), ), Container( height: 100, color: Colors.green, child: Center(child: Text('Custom Item 2')), ), Container( height: 100, color: Colors.blue, child: Center(child: Text('Custom Item 3')), ), // 添加更多的子项 ], ), ), ), SliverPadding( padding: const EdgeInsets.all(5), sliver: SliverList( delegate: SliverChildListDelegate( [ ListTile(title: Text('Item 1')), ListTile(title: Text('Item 2')), ListTile(title: Text('Item 3')), // 可以添加更多的 ListTile 或其他 Widget ], ), ), ) 那么这里的 Padding 是体现在两个 SliverList 之间的间距。 1.4 SliverOpacity理解了 SliverPadding 之后,再看类似的包装器就是很简单了 SliverOpacity( opacity: 0.5, sliver: SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return ListTile(title: Text('Item $index')); }, childCount: 100, ), ), ) SliverOpacity 组件允许您为 Sliver 设置透明度。它可以控制整个 Sliver 的可见性,对实现渐变效果非常有用。 1.5 DecoratedSliverDecoratedSliver( decoration: BoxDecoration( color: Colors.blue.withOpacity(0.2), borderRadius: BorderRadius.circular(10), ), sliver: SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return ListTile(title: Text('Item $index')); }, childCount: 100, ), ), ) DecoratedSliver 是一个用于给 Sliver 添加装饰效果的组件。它可以通过 BoxDecoration 来设置背景色、边框、阴影以及圆角等。 1.6 SliverVisibility 与 SliverOffstage居然透明度都可以有 Sliver 类型,那么显示隐藏的功能没道理没有啊。 SliverVisibility( visible: true, // 根据条件设置为 true 或 false sliver: SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return ListTile(title: Text('Item $index')); }, childCount: 10, ), ), SliverOffstage( offstage: !_isVisible, sliver: SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return ListTile(title: Text('Item $index')); }, childCount: 10, ), ), 占位与不占位的显示隐藏也是非常方便。 1.7 SliverMainAxisGroup 与 SliverCrossAxisGroup SliverMainAxisGroup( children: WidGET@[ SliverToBoxAdapter(child: Container(height: 100, color: Colors.red)), SliverToBoxAdapter(child: Container(height: 100, color: Colors.green)), SliverToBoxAdapter(child: Container(height: 100, color: Colors.blue)), ], ), 老版本中我们如果想要对列表分组我们可能需要导入一些第三方库,如 sticky_headers 之类的进行列表的分组,现在我们可以直接操作了。 我们在 SliverMainAxisGroup 中配合 SliverPersistentHeader 固定住分组的头部就可以实现分组的效果。 CustomScrollView( slivers: [ // 第一个组的头部 SliverPersistentHeader( pinned: true, delegate: _SliverAppBarDelegate( child: Container( color: Colors.blue, height: 60.0, alignment: Alignment.center, child: Text( 'Group 1', style: TextStyle(color: Colors.white, fontSize: 20), ), ), ), ), // 第一个组的内容 SliverMainAxisGroup( children: WidGET@[ SliverToBoxAdapter(child: Container(height: 100, color: Colors.red)), SliverToBoxAdapter(child: Container(height: 100, color: Colors.green)), SliverToBoxAdapter(child: Container(height: 100, color: Colors.blue)), ], ), // 第二个组的头部 SliverPersistentHeader( pinned: true, delegate: _SliverAppBarDelegate( child: Container( color: Colors.green, height: 60.0, alignment: Alignment.center, child: Text( 'Group 2', style: TextStyle(color: Colors.white, fontSize: 20), ), ), ), ), // 第二个组的内容 SliverMainAxisGroup( children: WidGET@[ SliverToBoxAdapter(child: Container(height: 100, color: Colors.yellow)), SliverToBoxAdapter(child: Container(height: 100, color: Colors.orange)), SliverToBoxAdapter(child: Container(height: 100, color: Colors.purple)), ], ), ], ), class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate { final Widget child; _SliverAppBarDelegate({required this.child}); @override double get minExtent = child != null ? 60.0 : 0.0; @override double get maxExtent = child != null ? 60.0 : 0.0; @override Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { return child; } @override bool shouldRebuild(_SliverAppBarDelegate oldDelegate) { return child != oldDelegate.child; } } 1.8 SliverAppbar 相关 SliverAppBar( expandedHeight: 200.0, // 展开的高度 floating: false, // 是否在滚动时保持在可见区域 pinned: true, // 是否固定在顶部 flexibleSpace: FlexibleSpaceBar( title: Text('SliverAppBar Example'), background: Image.network( 'xxxxxx', // 替换为你的图片链接 fit: BoxFit.cover, ), ), ), SliverAppBar 是一个非常强大的组件,用于创建可滚动的应用栏。它可以与其他 Sliver 组件(如 SliverList、SliverGrid 等)结合使用,提供灵活的滚动效果,有点类似 Android 中的灵活布局的效果。 SliverAppBar 的主要属性 expandedHeight: 指定 SliverAppBar 展开时的高度。 pinned: 设置为 true 时,AppBar 将在滚动到顶部时固定在屏幕顶部。 floating: 设置为 true 时,当向下滚动时,AppBar 会重新出现。 flexibleSpace: 用于定义可伸缩的空间,通常使用 FlexibleSpaceBar。 backgroundColor: 设置 AppBar 的背景色。 actions: 一个包含 IconButton 或其他小部件的列表,通常用于显示操作按钮。 SliverAppBar 虽然可以配合 SliverPersistentHeader 实现炫酷的效果,但是多半也是停留在 Demo 中,由于谷歌位太浓了,反倒是没有太多使用的机会。 在更新了 Flutter 3.24.0 之后,加入了全新版本 SliverFloatingHeader 、PinnedHeaderSliver、SliverResizingHeader 会更加的好用,出场机会更多了。 因为他们是对 SliverAppBar 的各种行为的有一次场景化封装,更加简化的使用了。并且并不局限于 SliverAppBar 这种只能是文本、图片的布局,可以自定义布局更方便的实现特定的效果了。后期会更加期待他们的出场。 1.9 其他除了上述的常用 Sliver 和对应的包装之外,当然还有非常多的 Sliver 和包装器,我没有穷举出来,只是这些常用的我们要了解,下面给出一个实战中的典型的示例。 二、场景复现效果图是这样的: 乍一看,这还不简单? 其实在我们的 LoadView 中加载的 Silver 就会有问题,因为 LoadView 是需要确定父布局的宽高的,如果没有圆角的装饰器,我们直接使用一个 expanded 的 LoadView 直接往下排就行了。 但是如果我们想要把 LoadView 中的 Sliver 真正的内容包裹起来使用装饰器去做就不好做。 最想到的是使用 Container 包裹,设置装饰器: Container( width: double.infinity, margin: EdgeInsets.only(left: 15, right: 15, bottom: 15), padding: EdgeInsets.only(top: ScreenUtil.getStatusBarH(context)), decoration: BoxDecoration( color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度 borderRadius: BorderRadius.circular(5), // 设置圆角 ), child: LoadStateLayout( state: controller.loadingState, errorMessage: controller.errorMessage, errorRetry: () { controller.retryRequest(); }, successSliverWidget: [ SliverList( delegate: SliverChildBuilderDelegate((context, index) { return ReportStaffRequestItem(item: state.datas[index]); }, childCount: state.datas.length), ), ], ), ).expanded(), 我们对 Container 设置 expanded 之后它的高度是确定的,那么 LoadView 有明确的宽高是没问题的,但是此时就是剩余的高度全部都被装饰了,没有达到我们动态列表的包裹内容装饰的效果。 那么我们外层包裹一个 Column 不就行了吗,内部就是高度自适应。 Column( children: [ Container( width: double.infinity, margin: EdgeInsets.only(left: 15, right: 15, bottom: 15), padding: EdgeInsets.only(top: ScreenUtil.getStatusBarH(context)), decoration: BoxDecoration( color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度 borderRadius: BorderRadius.circular(5), // 设置圆角 ), child: LoadStateLayout( state: controller.loadingState, errorMessage: controller.errorMessage, errorRetry: () { controller.retryRequest(); }, successSliverWidget: [ SliverList( delegate: SliverChildBuilderDelegate((context, index) { return ReportStaffRequestItem(item: state.datas[index]); }, childCount: state.datas.length), ), ], ), ), ], ) 结果大家肯定是知道的,报错了,问题就出在高度自适应的问题上,因为 LoadStateLayout 需要明确的宽高,因为内部有错误和空布局的处理。 那怎么办?修改 LoadStateLayout 的代码吗? 其实聪明的你肯定发现了,在前文中我们介绍了 Sliver 与装饰器的介绍,我们可以直接通过装饰器来实现: LoadStateLayout( state: controller.loadingState, errorMessage: controller.errorMessage, errorRetry: () { controller.retryRequest(); }, successSliverWidget: [ SliverPadding( padding: const EdgeInsets.only(left: 15,right: 15,bottom: 15), sliver: DecoratedSliver( decoration: BoxDecoration( color: const Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度 borderRadius: BorderRadius.circular(5), // 设置圆角 ), sliver: SliverList( delegate: SliverChildBuilderDelegate((context, index) { return ReportStaffRequestItem(item: state.datas[index]); }, childCount: state.datas.length, ), ), ), ), ], ).expanded(), 效果: 故意这么写就是为了清楚,这里的装饰器是给 Sliver 层级的装饰,而不是内部的 Item 子布局,如果要达到效果图的样子,我们只需要改内部的布局间距即可。 最终效果: 总结本文我们介绍了常见的 Sliver 以及对应的装饰器,后面我们介绍了如何进行实战的开发。 在我们进行开发的过程中,牢记每一个 Sliver,不管是单个 Sliver 控件还是 Sliver 控件组,我们都可以分别进行装饰,不管是动画效果,渐变显隐,还是边框装饰,间距设置都是可以更方便的实现的。 本文对应的 Fultter 版本是 3.19.2 以及 3.24.0 ,由于 iOS 权限的问题,我相信大家的 Flutter 版本至少都已经升级到 3.19.+ 了吧,所以这些 Sliver 都是可以用的,其实我们看到谷歌也是一直在更新 Sliver 的控件与包装器,越来越方便了呢。 那本文的代码比较简单,相对比较基础,并且全部的代码也已经在文中展出,这里就不放出项目链接了。 今天的分享就到这里啦,当然如果你有其他的更多的更好的实现方式,也希望大家能评论区交流一起学习进步。如果我的文章有错别字,不通顺的,或者代码、注释、有错漏的地方,同学们都可以指出修正。 如果感觉本文对你有一点的启发和帮助,还望你能点赞支持一下,你的支持对我真的很重要。 Ok,这一期就此完结。 点击关注公众号,“技术干货”及时达! 阅读原文

上一篇:2024-06-28_再现“四库全书”成卷历程-- 佳能EOS R5 C 在纪录片《跨越时空的四库全书》拍摄中的多角度应用 下一篇:2025-02-22_腾讯研究院AI每周关键词Top50

TAG标签:

16
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设网站改版域名注册主机空间手机网站建设网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。
项目经理在线

相关阅读 更多>>

猜您喜欢更多>>

我们已经准备好了,你呢?
2022我们与您携手共赢,为您的企业营销保驾护航!

不达标就退款

高性价比建站

免费网站代备案

1对1原创设计服务

7×24小时售后支持

 

全国免费咨询:

13245491521

业务咨询:13245491521 / 13245491521

节假值班:13245491521()

联系地址:

Copyright © 2019-2025      ICP备案:沪ICP备19027192号-6 法律顾问:律师XXX支持

在线
客服

技术在线服务时间:9:00-20:00

在网站开发,您对接的直接是技术员,而非客服传话!

电话
咨询

13245491521
7*24小时客服热线

13245491521
项目经理手机

微信
咨询

加微信获取报价