重识Flutter — 探索Slivers的奇妙世界(综合实例)

news2024/10/6 14:37:08

前言

在前三篇文章中,从为什么要使用Sliver,再根据使用频率逐个解析Slivers系列的组件。相信您已经入门了Sliver的世界。为了更好的将Slivers相关的组件结合起来使用,本文将通过一个综合的案例来帮助你理解。

源代码:https://www.aliyundrive.com/s/mPCDFwRv4Rm

效果图

话不多说,先上效果图,有图有真相!

页面框架搭建

顶部

SliverAppBar(
  //指定状态栏(status bar)的亮度为暗色
  systemOverlayStyle:
  const SystemUiOverlayStyle(statusBarBrightness: Brightness.dark),
  expandedHeight: 275.0,
  backgroundColor: Colors.white,
  elevation: 0.0,
  pinned: true,
  stretch: true,
  flexibleSpace: FlexibleSpaceBar(
    background: Image.asset(
      'assets/images/back_image.png',
      fit: BoxFit.cover,
    ),
    stretchModes: const [
      StretchMode.blurBackground,
      StretchMode.zoomBackground,
    ],
  ),
  leadingWidth: 80.0,
  //裁剪为圆角矩形
  leading: ClipRRect(
    borderRadius: BorderRadius.circular(56.0),
    //模糊滤镜
    child: BackdropFilter(
      filter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0),
      child: Container(
        height: 56.0,
        width: 56.0,
        alignment: Alignment.center,
        decoration: BoxDecoration(
          shape: BoxShape.circle,
          color: Colors.white.withOpacity(0.20),
        ),
        child: SvgPicture.asset('assets/images/icon/arrow-ios-back-outline.svg'),
      ),
    ),
  ),
);

底部装饰

bottom: PreferredSize(
  preferredSize: const Size.fromHeight(0.0),
  child: Container(
    height: 32.0,
    alignment: Alignment.center,
    decoration: const BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.only(
        topLeft: Radius.circular(32.0),
        topRight: Radius.circular(32.0),
      ),
    ),
    child: Container(
      width: 40.0,
      height: 5.0,
      decoration: BoxDecoration(
        color: kOutlineColor,
        borderRadius: BorderRadius.circular(100.0),
      ),
    ),
  ),
),

使用SliverToBoxAdapter来使用基于Box协议的组件

SliverToBoxAdapter(
  child: Padding(
    padding: EdgeInsets.symmetric(horizontal: 20),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          '意大利面拌42号混凝土',
          style: Theme.of(context).textTheme.titleMedium,
        ),
      	...
      ],
    ),
  ),
),

通过SliverPersistentHeader制作菜品展示区域

class Menu extends SliverPersistentHeaderDelegate {
    ...

  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    ...
    return Container(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
        	...
          Text(
               '菜品展示',
               style: Theme.of(context).textTheme.titleMedium,
          ),
          Expanded(
            child: Stack(
              children: [
              	//控制层叠关系
                if (percent > uploadlimit) ...[
                  card,
                  bottomsliverbar
                ] else ...[
                  bottomsliverbar,
                  card
                ]
              ],
            ),
          ),
        ],
      ),
    );
  }
	
  double get maxExtent => maxExtended;

  
  double get minExtent => minExtended;

  
  bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) =>
      false;
}

反转叠加动画通过Stack结合Transform实现


Widget build(
    BuildContext context, double shrinkOffset, bool overlapsContent) {
	//shrinkOffset为SliverPersistentHeader滚动偏移量,用于对应图片的偏移程度
  final percent = shrinkOffset / 180;
	//限制图片偏移的触发范围
  final uploadlimit = 13 / 120;
	//使用clamp限制范围
  final valueback = (1 - percent - 0.77).clamp(0, uploadlimit);
	//将percent的值取平方,用于菜品展示图片下方背景块的位置偏移
  final fixrotation = pow(percent, 1.5);
	//背景
  final bottomsliverbar = _CustomBottomSliverBar(
      size: size, fixrotation: fixrotation, percent: percent);
	//菜品图片
  final card = _CoverCard(
      valueback: valueback,
      size: size,
      percent: percent,
      uploadlimit: uploadlimit);
  return Container(
    ...
  );
}

图片变换的布局

使用 Matrix4.identity()..rotateZ(...)实现绕 Z 轴的旋转变换。

Positioned(
    top: size.height * 0.005,
    left: size.width / 24,
    child: Transform(
      alignment: Alignment.topRight,
      transform: Matrix4.identity()
        ..rotateZ(percent > uploadlimit
            ? (valueback * angleForCard)
            : percent * angleForCard),
      child: CoverPhoto(size: size),
 ))

//CoverPhoto
Container(
	...
  decoration: BoxDecoration(
      borderRadius: BorderRadius.circular(12),
      image: DecorationImage(
        ...
        fit: BoxFit.cover,
      )),
)

图片不规则背景+修复动画

背景块通过CustomPainter进行绘制


void paint(Canvas canvas, Size size) {
  final paint = Paint();
  paint.color = backgroundcolor;
  paint.style = PaintingStyle.fill;
  paint.strokeWidth = 10;
  final path = Path();
  path.moveTo(0, size.height);
  path.lineTo(size.width, size.height);
  path.lineTo(size.width, 0);
  path.lineTo(size.width * 0.27, 0);
  canvas.drawPath(path, paint);
}

修复动画通过Positionedleft做出视觉上的一个视差

Positioned(
    right: 0,
    bottom: 0,
    left: -size.width * fixrotation.clamp(0, 0.35),
    child: Container(
      height: size.height * 0.12,
      child: Stack(
        fit: StackFit.expand,
        children: [
          CustomPaint(
            painter: CutRectangle(),
          )
        ],
      ),
  ))

剩余部分

剩余部分都是通过SliverToBoxAdapter来进行实现,具体布局的内容不是本文的重点,就不过多阐述了,详见源代码。

总结

至此,三篇组件分解文章+一篇综合实战文章,我们学习了Sliver的使用和特性,相信您已经进入了Sliver的世界。我所写的也只是它魅力的冰山一角Sliver系列组件是用于创建灵活的滚动界面和复杂布局的关键,那么请继续探索Sliver的世界,利用其强大的特性和灵活的组合方式,创建出更加有趣和具有交互性的滚动界面吧~(后续还会有更多的使用教程、源码分解…)

关于我

Hello,我是Taxze,如果您觉得文章对您有价值,希望您能给我的文章点个❤️,有问题需要联系我的话:我在这里 。如果您觉得文章还差了那么点东西,也请通过关注督促我写出更好的文章~万一哪天我进步了呢?😝

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/704522.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【动态规划】LeetCode 583. 两个字符串的删除操作 Java

583. 两个字符串的删除操作 我的代码,错误代码,只考虑到了字母出现的次数,没有考虑到两个字符串中字母出现的顺序 class Solution {public int minDistance(String word1, String word2) {int[] arr1 new int[26];int[] arr2 new int[26];…

Fiddler抓包工具笔记

一、简介 Fiddler代理相当于中介的角色 快捷键ShiftF5去缓存刷新 二、抓包 1. 设置过滤器 没有设置过滤器的话,会抓所有的包,非常乱会混淆 隐藏包含这些内容的URL 2. 快速定位到需要的包 点击:Webforms菜单 界面分析: …

SQlite3 编译

参考博客:https://blog.csdn.net/flowerspring/article/details/121268403 1.下载C源码以及def文件https://www.sqlite.org/download.html 2. 下载完成之后解压 sqlite-amalgamation获取C源码,解压sqlite-dll-win32-xx获取里面的def文件。 3.新建sqlite…

前端vue入门(纯代码)18

不管何时何地,永远保持热爱,永远积极向上!!! 【20.尚硅谷GitHub搜索案例_vue-resource实现】 1.vue-resource vue-resource 是 vue 中一个用于发送请求的插件。 vue 发送请求推荐使用 axios ,vue-resourc…

2023上半年软考系统分析师科目一整理-23

2023上半年软考系统分析师科目一整理-23 对于如下所示的序列图所描述的场景,最适合于采用的设计模式是(30);该模式适用的场合是(31)。 A.Visitor B.Strategy C.Observe…

TI AM64x工业核心板规格书(双核ARM Cortex-A53 + 单/四核Cortex-R5F + 单核Cortex-M4F,主频1GHz)

1 核心板简介 创龙科技SOM-TL64x是一款基于TI Sitara系列AM64x双核ARM Cortex-A53 单/四核Cortex-R5F 单核Cortex-M4F设计的多核工业级核心板,通过工业级B2B连接器引出5x TSN Ethernet、9x UART、2x CAN-FD、GPMC、PCIe/USB 3.1等接口。核心板经过专业的PCB Layo…

【C++练习】string:字符串题型训练(5道编程题)

【C练习】string:字符串题型训练 Ⅰ.字符串中的第一个唯一字符Ⅱ.字符串最后一个单词的长度Ⅲ.把字符串转换成整数Ⅳ.字符串相加Ⅴ.反转字符串 Ⅰ.字符串中的第一个唯一字符 解题思路: 第一种方法: 两次遍历 1.第一次遍历,将每个字符出现的次…

【HTTP 协议2】如何构造 HTTP 请求

文章目录 前言一、地址栏输入二、HTML 特殊标签三、form 表单四、ajax总结 前言 各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你: 📕 JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等 📗 Java数据结…

【Echarts】配置项归纳

【Echarts】配置项归纳 一、title二、legend三、grid四、xAxis/yAxis五、polar六、radiusAxis七、angleAxis八、radar九、dataZoom1. 内置型数据区域缩放组件2. 滑动条型数据区域缩放组件3. 框选型数据区域缩放组件 十、tooltip十一、axisPointer十二、toolbox十三、brush十四、…

不定长图文模型训练

文章目录 生成数据集模型选择计算均值和标准差训练代码测试集测试 生成数据集 import os import random from PIL import Image, ImageDraw, ImageFont, ImageFilter from io import BytesIO import timedef main():_first_num random.randint(1, 1000)_code_style [加, 减,…

【uniapp开发小程序】实现粘贴一段文字后,自动识别到姓名/手机号/收货地址

一、需求 在uni-app中开发小程序&#xff0c;实现粘贴一段文字后自动识别到手机号&#xff0c;并将手机号前面的内容作为姓名&#xff0c;手机号后面的内容作为收货地址&#xff0c;并去除其中的特殊字符和前缀标识。 实现效果&#xff1a; 二、实现方式&#xff1a; <…

【vue】vue.js中引入组件

目录 ⭐️一、点击按钮1弹出弹窗⭐️二、vue.js引入组件具体步骤1、创建自定义组件的文件夹&#xff08;以弹窗组件为例&#xff09;2、在index.vue中引入keyProductsTip.vue模块3、在index.vue中引入组件4、在index.vue中使用组件&#xff0c;点击按钮打开弹窗5、index.vue中的…

高级web前端开发工程师的主要职责模板(合集)

高级web前端开发工程师的主要职责模板1 职责&#xff1a; 1、web端页面的制作、开发和优化; 2、编写静态和动态页面和交互、特效等功能的脚本程序; 3、开发基于HTML5技术的可灵活定制、可扩展的前端UI组件; 4、优化前端架构&#xff0c;提高系统的灵活性和可扩展性; 5、开…

【AUTOSAR】BMS开发实际项目讲解(二十六)----电池管理系统低压上下电功能

低压上下电功能 关联的系统需求 Sys_Req_3101、Sys_Req_3102、Sys_Req_3103、Sys_Req_3104; 功能实现描述 低压上电管理 ID Description ASIL Ref. LVM-101 当系统检测到如下任一信号有效时&#xff1a; 整车CAN、ACC、IGN、CC、CP唤醒、一路预留硬线唤醒系统应…

Java安全——存取控制器

Java安全 存取控制器 Java安全中的存取控制器是一种技术&#xff0c;用于控制访问应用程序中的资源。它的基本思想是允许或拒绝特定用户对系统资源的访问。存取控制器包括四个关键部分: 主体(subject), 权限(permission), 对象(object)和存取控制策略(access control policy)。…

【vue3】学生管理案例

此案例可以分为4个部分&#xff1a; 渲染学生列表新增学生删除学生搜索学生 涉及的知识点主要为v-model双向绑定数据。 页面&#xff1a; <div id"main"><table><tr><td>学号</td><td>姓名</td><td>新增时间<…

121.【ElasticSearch伪京东搜索】

模仿京东搜索 (一)、搭建环境0.启动ElasticSearch和head和kblian(1).启动EslaticSearch (9200)(2).启动Es-head (9101)(3).启动 Kibana (5602) 1.项目依赖2.启动测试 (二)、爬虫1.数据从哪里获取2.导入爬虫的依赖3.编写爬虫工具类(1).实体类(2).工具类编写 4.导入配置类 (三)、…

Selenium系列(四) - 详细解读鼠标操作

引入HTML页面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>测试笔记</title> </head> <body><a>用户名:</a> <input id"username" class"userna…

航空枢纽联通亚欧,开放合作互利共赢 —乌鲁木齐国际航空枢纽建设论坛将于7月6日召开

为创新开放型经济体制&#xff0c;加快建设对外开放大通道&#xff0c;更好利用国际国内两个市场、两种资源&#xff0c;积极服务和融入双循环新发展格局&#xff0c;促进经济高质量发展&#xff0c;2023年7月6日-7日&#xff0c;以“航空枢纽联通亚欧&#xff0c;开放合作互利…

基于matlab使用单眼摄像机图像数据构建室内环境地图并估计摄像机的轨迹(附源码)

一、前言 视觉同步定位和映射 &#xff08;vSLAM&#xff09; 是指计算摄像机相对于周围环境的位置和方向&#xff0c;同时映射环境的过程。该过程仅使用来自相机的视觉输入。vSLAM 的应用包括增强现实、机器人和自动驾驶。 此示例演示如何处理来自单眼摄像机的图像数据&…