本文目录

  • 前言
  • 基本用法
  • 实现原理

前言

在前面实践组件的开发中,我们做了一个登录的界面,里面有一个组件Hero,不知道大家是否记得?当时没有展开来说,是因为它属于动画的内容,本文就要重点讲解Hero动画。

做过Java开发Android的程序员应该都清楚,Shared Element Transition可以让Activity或Fragment做出流畅的动画,同样,在Flutter开发中,Hero动画也能实现类似的效果。简单来说,Hero的作用就是在路由之间做出流畅的转场动画。

基本用法

Hero组件的用法是需要同时定义源组件和目标组件,其中源组件和目标组件被Hero包裹在需要动画控制的组件外面,如果有一方不指定,在有些情况下,界面就会卡死,我们先来看看它的基本用法,首先是main.dart代码:

class _MyHomePageState extends State<MyHomePage> {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("我是第一个界面"),),body: Center(child: GestureDetector(child: Hero(tag: "tag1",child: FlutterLogo(size: 200,),),onTap: () {Navigator.push(context, MaterialPageRoute(builder: (BuildContext context)=>CustomFlutterLogoPage()));},),),);}
}

代码很简单,就是监听点击事件ontap,hero包裹FlutterLogo组件,然后点击跳转到第二个界面。接着我们再来看看第二个页面CustomFlutterLogo.dart的代码:

import 'package:flutter/material.dart';class CustomFlutterLogoPage extends StatefulWidget {CustomFlutterLogoPage({Key key, this.title}) : super(key: key);final String title;@override_CustomFlutterLogoState createState() => _CustomFlutterLogoState();
}class _CustomFlutterLogoState extends State<CustomFlutterLogoPage> {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("我是第二个页面"),),body: Center(child: Hero(tag: "tag2",child: CustomFlutterLogo(size: 400,name: "我是第二个页面",),),),);}}class CustomFlutterLogo extends StatelessWidget{final double size;final String name;CustomFlutterLogo({this.size=200.0,this.name});@overrideWidget build(BuildContext context) {return Container(child: Center(child: FlutterLogo(size: this.size,),),);}}

这段代码也很简单,就是常用的组件,只是在外层套了一层Hero动画组件,不过这里有一点我们需要注意,hero里面有一个tag属性,必须写上,不然会报错,不信的读者,可以删除后运行试试。

实现原理

我们基本已经掌握了Hero路由跳转动画的用法,但我们不能只看表面,不明其原理,因为后面讲解的动画也会涉及到这些知识,所以我们必须掌握。

Hero动画,它的整个运动过程分为3个步骤,即动画开始(t=0.0),动画进行中,动画结束(t=1.0),下面是Hero动画运动示意图:
如上图所示,两个路由之间还有一个Overlay层。在动画开始时,Flutter会计算出Hero的位置并复制一份,然后绘制到Overlay层上。复制的Hero和源Hero的大小是一致的,并且该Hero是在所有路由之上。在动画实现的过程中,Flutter会逐渐把源Hero移除屏幕。在动画进行中Flutter是依靠Tween来实现,通过createRectTween属性把Tween传给Hero。Hero内部默认使用MeterialRectArcTween的曲线路径进行移动动画的操作。在动画结束时,Flutter将Overlay中的Hero移除,且完成了Hero在目标路由上的显示,这时Overlay是空白的。

Hero中所有变换都是通过HeroController来实现的,HeroController是在MeterialApp中通过initState和didUpdateWidget方法来完成初始化的,源码如下所示:

class _MaterialAppState extends State<MaterialApp>{HeroController heroController;@overridevoid initState(){super.initState();_heroController=HeroController(createRectTween:_createRectTween);_updateNavigator();}@overridevoid didUpdateWidget(MaterialApp oldWidget){super.didUpdateWidget(oldWidget);if(widget.navigatorKey!=oldWidget.navigatorKey){_heroController=HeroController(createRectTween:_createRectTween);}_updateNavigator();}RectTween _createRectTween(Rect begin,Rect end){return MaterialRectArcTween(begin:begin,end:end);}
}

在初始化HeroController时,Flutter携带了一个参数,就是_createRectTween,该参数返回的默认项就是MaterialRectArcTween。Flutter源码里还为我们实现了第二种RectTween返回值,即MaterialRectCenterArcTween。由此可见,可以对createRectTween进行自定义。我们再看看HeroController的具体内容,代码如下:

@override
void didPush(Route<dynamic> route,Route<dynamic> previousRoute){assert(navigator!=null);assert(route!=null);_maybeStartHeroTransition(previousRoute,route,HeroFlightDirection.push,false);
}@override
void didPop(Route<dynamic> route,Route<dynamic> previousRoute){assert(navigator!=null);assert(route!=null);_maybeStartHeroTransition(route,previousRoute,HeroFlightDirection.pop,false);
}

HeroController其实继承的是NavigatorObserver。在路由操作的didPush和didPop回调方法里,可以调用_maybeStartHeroTransition,并通过WidgetsBinding把源路由,目标路由,HeroController关联起来。在使用didPush和didPop回调时,通过调用_startHeroTransition方法让Hero动起来,只不过前者是正向的,后者是逆向的。

Flutter(十六)——Hero动画相关推荐

  1. Python 之 matplotlib (十六)Animation动画

    代码: import matplotlib.pyplot as plt import numpy as np from matplotlib import animationfig, ax = plt ...

  2. 【Flutter】Hero 动画 ( Hero 动画使用流程 | 创建 Hero 动画核心组件 | 创建源页面 | 创建目的页面 | 页面跳转 )

    文章目录 ◯.Hero 动画简介 一.创建 Hero 动画核心组件 二.创建源页面 三.创建目的页面 四.页面跳转 五.完整代码示例 六.相关资源 ◯.Hero 动画简介 Hero Widget 动画 ...

  3. 【Flutter】Hero 动画 ( Hero 实现径向动画 | Hero 组件 createRectTween 设置 )

    文章目录 ◯.Hero 构造函数 一.圆形方形组件 二.创建页面 1 的组件 ( Hero 组件 1 ) 三.创建页面 2 的组件 ( Hero 组件 2 ) 四.完整代码示例 五.相关资源 ◯.He ...

  4. flash动画设计期末作业_「2019年下学期」第二十五二十六节:期末作品三-吉祥物设计...

    初心 伟大的艺术品不必追随潮流,他本身就能引领潮流. 课前准备 软件安装 [2019(上)]<三维建模与动画设计> [2019年下学期]第一节:选修介绍及选修人数确定 [2019年下学期] ...

  5. Flutter Hero动画让你的APP页面切换充满动效 不一样的体验 不一样的细节处理

    优美的应用体验 来自于细节的处理,更源自于码农的自我要求与努力,当然也需要码农年轻灵活的思维. 本文章实现的Demo效果,如下图所示: 1 首先是页面的主体 在这里使用的是Scaffold脚手架来构建 ...

  6. 31、Flutter之Hero动画

    Flutter Hero动画 Hero指的是可以在路由(页面)之间"飞行"的widget. 使用Flutter的Hero widget创建hero动画. 将 hero从一个路由飞到 ...

  7. Flutter动画 4 - Hero动画

    概述 花瓣App的转场动画,这么多年还是没变,还是图片转场动画. 网上有很多人实现过相关效果,先前骚栋18年在做iOS项目的时候,也实现的类似的效果,但是全程实现起来还是比较麻烦,需要自己来定义转场动 ...

  8. flutter 九宫格菜单_Flutter 九宫格及Hero动画

    class LXPhotosView extends StatefulWidget { //数据资源 final List list; //主轴间距 final double mainAxisPadd ...

  9. 整理第十六届全国大学智能车竞赛比赛数据

    简 介: 整理提交了第十六届全国大学生智能车总决赛的数据. 关键词: 智能车竞赛,总决赛 #mermaid-svg-QA3wJFTY8KGVWeUO {font-family:"trebuc ...

最新文章

  1. python 打印数组变量_使用Python将数组的元素导出到变量中(unpacking)
  2. ​基于BCI的现代神经反馈有助于认知增强(二)
  3. php图片生成缩略图_PHP生成图片缩略图类示例
  4. visual studio code配置项
  5. 如何减少tomcat内存使用量?
  6. 【数据结构与算法】之深入解析“搜索旋转排序数组”的求解思路与算法示例
  7. CALL FUNCTION START NEW TASK
  8. Java DataOutputStream size()方法及示例
  9. jQuery常用的元素查找方法总结 .
  10. 别让Vue3.0的谣言害了你!
  11. 前端大神:如何看待 React Server Components?
  12. 学习BIOS与CMOS区别
  13. 摘要算法、对称加密、非对称加密、数字签名、数字证书浅析
  14. 数学建模论文写作方法
  15. 网站SQL注入漏洞检测
  16. pm2 启动 nodejs 项目
  17. mysql聚合函数匹配_MySQL 05章_模糊查询和聚合函数
  18. python你好代码-再见,Python。你好,Go语言。
  19. linux 6.7 远程端口,CentOS6.7安装vncserver及xrdp实现远程桌面
  20. Sort Sort Sort

热门文章

  1. 全基因组测序 从头测序(de novo sequencing) 重测序(re-sequencing)
  2. html5 手机模板 解放区,解放区异形模板
  3. 三部曲简史mobi_尤瓦尔.赫拉利简史三部曲(电子书)
  4. 计网/数据库面试题(更新中ing~~)
  5. 【笔记】获取中国电信家庭宽带烽火光猫HG221GS超级管理密码的方法步骤
  6. 如何屏蔽csdn百度广告
  7. 板栗花生鸡脚汤——好女人和老火汤同样需要用心品位
  8. 才茂CM520如何通过4G物联网卡将信号发送到PC端
  9. linux eval命令详解,linux命令详解——eval
  10. java 随机字母数字_Java生成字母和数字组成的随机字符串