今天给大家介绍的是Flutter中独有的动画,Hero动画,非常的炫酷,接下来就步入正题吧~
Hero动画介绍
Hero指的是可以在路由(页面)之间“飞行”的widget,简单来说Hero动画就是在路由切换时,有一个共享的widget可以在新旧路由间切换。由于共享的widget在新旧路由页面上的位置、外观可能有所差异,所以在路由切换时会从旧路逐渐过渡到新路由中的指定位置,这样就会产生一个Hero动画。
先来看看要完成的效果吧:
效果图(1.1):
分析:
通过效果图可以看出,点击图片或者文字,完成了图片的由小到大的动画效果,并且完成了页面的切换,以及文字布局在不同位置的展示, 水波纹点击效果
好了,咋们先不考虑Hero动画如何使用,先把2个页面的布局,图片,文字给写出来,以及水波纹效果
class HerpPracticePage extends StatefulWidget {
@override
_HerpPracticePageState createState() => _HerpPracticePageState();
}
class _HerpPracticePageState extends State<HerpPracticePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Hero动画练习"),
),
body: Container(
color: Colors.transparent,
//左右排列布局
child: Material(
//水波纹效果
child: InkWell(
onTap: () {
},
child: Row(
//主轴方向开始对齐 在这里是左对齐
mainAxisAlignment: MainAxisAlignment.start,
//交叉轴上开始对齐 在这里是顶部对齐
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//左侧图片
initLeftIcon(),
//右侧文字
initRightTxt(),
],
),
)),
),
);
}
/**
* 左侧图片
*/
Widget initLeftIcon() {
return Container(
child: Image.network(
"https://raw.githubusercontent.com/flutter/website/master/examples/_animation/hero_animation/images/flippers-alpha.png",
width: 150,
height: 80,
),
);
}
/**
* 右侧文字
*/
Widget initRightTxt() {
//建议使用Expanded包裹,这样防止上下布局Text文本溢出导致错误!
return Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text("今天礼拜六"),
Text("我在公司认真的学习flutter,正在学习Hero动画,有点难,不过我会克服的!!"),
],
));
}
}
这段代码十分简单,先通过Row()组件完成布局的左右(水平)排列,
将图片和文字区分开,
然后在在文字区域使用Cloumn()组件完成布局的上下(垂直)排列,
将文字上下排列开
然后在使用InkWell设置水波纹效果
这里有2处地方需要注意:
- 使用Inkwell一定要写OnTap(){}单击事件属性
- 在使用Column()组件时建议用Expanded()包裹一下,若Column()组件屏幕溢出,则会报错,Expanded()会展开,常用于占满父容器垂直高度,同样在使用Row()组件的时候也可以使用
跳转到的页面:
class JumpPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("这是跳转页面"),
),
body: initJumpPageBody(context),
);
}
/**
* JumpPage的Body布局
*/
initJumpPageBody(BuildContext context) {
return Container(
child: Column(
children: [
//图片
initJumpIcon(context),
//文本
initJumpTxt(context),
],
),
);
}
/**
* 初始化Jump图片布局
*/
initJumpIcon(BuildContext context) {
return Material(
child: InkWell(
onTap: () {
//返回上一页面
Navigator.of(context).pop();
},
child: Image.network(
"https://raw.githubusercontent.com/flutter/website/master/examples/_animation/hero_animation/images/flippers-alpha.png",
width: 300,
height: 160,
),
),
);
}
/*
文字布局
*/
initJumpTxt(BuildContext context) {
return Container(
padding: EdgeInsets.all(20),
child: Text(
"我在公司认真的学习flutter,正在学习Hero动画,有点难,不过我会克服的!!",
),
);
}
}
这段代码更不需要过多解释,就是一张图片,和一段文字
接下来就到了关键的时候,两个界面都初始化完成了,之后使用Hero()组件进行包裹
我们需要进行的是2个图片之间的’飞’,所以只需要对图片使用Hero()组件即可
第一个页面图片添加Hero()组件,并添加Tag
/**
* 左侧图片
*/
Widget initLeftIcon() {
return Container(
child: Hero(
tag: "HeroPractice",
child: Image.network(
"https://raw.githubusercontent.com/flutter/website/master/examples/_animation/hero_animation/images/flippers-alpha.png",
width: 150,
height: 80,
),
),
);
}
跳转到的页面图片:
/**
* 初始化Jump图片布局
*/
initJumpIcon(BuildContext context) {
return InkWell(
onTap: () {
Navigator.of(context).pop();
},
child: Hero(
tag: "HeroPractice",
child: Image.network(
"https://raw.githubusercontent.com/flutter/website/master/examples/_animation/hero_animation/images/flippers-alpha.png",
width: 300,
height: 160,
),
),
);
}
这里需要注意的是:
- Hero()中tag参数是2个页面之间的唯一标识,不能重复且唯一的!!!
- 我看有些博客写Hero()中子组件必须用Material()包裹,可能版本不一样,我使用的过程中不包裹也可以.如若报错,加上试试吧~
- 在使用Hero()的时候,一定不能包裹太多的子组件,否则的话就会有这种效果,请看效果图(1.2)
效果图(1.2):
从效果图(1.2)中可以看出,点击跳转时,图片背景会有一层白色的状态,然而返回的时候并没有,这就是Hero()包裹太多子组件导致的,别问我怎么知道的,我心里苦o(╥﹏╥)o…(下一章这里有妙用!!!)
现在已经完成了70%,现在只需要完成在2秒内跳转中的动画,由不透明==>>透明即可大功告成!
这里只需要在跳转页面时使用PageRouteBuilder自定义路由即可
onTap: () {
//跳转页面
Navigator.of(context).push(initPageRouteBuilder());
},
/**
* 初始化跳转页面参数
*/
Route<Object> initPageRouteBuilder() {
return PageRouteBuilder(
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
//设置跳转到的页面
return JumpPage();
},
//打开新页面的时间
transitionDuration: Duration(seconds: 2),
//关闭页面的时间
reverseTransitionDuration: Duration(seconds: 2),
//跳转页面的动画
transitionsBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
//跳转页面动画
> 这里是引用
return initFadeTransition(animation, child);
},
);
}
PageRouteBuilder自定义路由,加粗是必加参数
PageRouteBuilder参数 | 类型 | 说明 |
---|---|---|
pageBuilder | RoutePageBuilder | 一般用来返回跳转页面 |
transitionDuration | Duration | 用来设置打开新页面的时间 |
reverseTransitionDuration | Duration | 关闭页面的时间 |
transitionsBuilder | RoutePageBuilder | 用来设置动画 |
跳转页面动画:
/**
* 透明动画
*/
Widget initFadeTransition(Animation<double> animation, Widget child) {
return FadeTransition(
opacity: Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
parent: animation,
curve: Curves.linear,
)),
child: child,
);
}
这段代码在Flutter AnimatedWidget,AnimatedBuilder动画(2.4)讲过类似的,当时是获取的帧,现在只是透明度变化,没有什么区别,这里就不在重复说啦
上一章:Flutter AnimatedWidget,AnimatedBuilder动画(2.4)
原创不易,您的点赞就是对我最大的支持,留下您的点赞吧~