为了账号安全,请及时绑定邮箱和手机立即绑定

[- Flutter小福利 -] Hero转场组件共享 — 附赠-路由动画工具类

标签:
WebApp

最近比较忙,很少发文章了。今天抽空把Hero的转场组件共享说一下
顺便发个转场的动画福利类,可以定义转场的时间,曲线,别客气,随便拿去用。
废话不多说,先看图:


  • 1.透明:FadeRouter



16cea75c8ccad375?imageslim




  • 2.缩放:ScaleRouter



16cea698ff00bfd0?imageslim




  • 3.旋转:RotateRouter



16cea72133b2e1be?imageslim




  • 4.透明+缩放+旋转



16cea7a089749fbf?imageslim



  • 5.右--->左:Right2LeftRouter



16cea5cb030114e4?imageslim




  • 6.左--->右:Left2RightRouter



16cea62cb5618377?imageslim




  • 7.上--->下:Top2BottomRouter



16cea652b07ebf67?imageslim




  • 8.下--->上:Bottom2TopRouter



16cea844e322a2f4?imageslim




Hero元素共享

也许上面吸引你的不是界面跳转的动画,而是那个头像神奇般的轨迹。下面就来说一下如何实现。

起始页:OriginPage
class OriginPage extends StatelessWidget {   @override   Widget build(BuildContext context) {       var hero= Hero(//----定义一个Hero,并添加tag标签,此中组件共享         tag: 'user-head',         child: ClipRRect(           borderRadius: BorderRadius.all(Radius.circular(30)),           child: Image.asset(             "images/mani.jpg",width: 60,height: 60,fit: BoxFit.cover,           ),         ),       );       var container= Container(//容器,没啥好说的         alignment: Alignment(-0.8, -0.8),         child: hero,         width: 250,         height: 250*0.618,         decoration: BoxDecoration(//添加渐变色         gradient: LinearGradient(colors: [Colors.red.withAlpha(99),Colors.yellow.withAlpha(189),Colors.green.withAlpha(88),Colors.blue.withAlpha(230)])       ),);     return Scaffold(       body: Center(//点击跳转         child: GestureDetector(child: Card(elevation:5,child:container ,),onTap: (){           _toNext(context);         },),       ),     );   }   void _toNext(context) {//跳转路由     Navigator.push(         context, //      FadeRouter(child:TargetPage()), //      ScaleRouter(child:TargetPage()), //      RotateRouter(child:TargetPage()), //      ScaleFadeRotateRouter(child:TargetPage()), //      Right2LeftRouter(child:TargetPage()), //      Left2RightRouter(child:TargetPage()), //      Top2BottomRouter(child:TargetPage()),       Bottom2TopRouter(child:TargetPage()),//跳转+动画     );   } } 复制代码
目标页:TargetPage
class TargetPage extends StatelessWidget {      @override   Widget build(BuildContext context) {     var hero=Hero(//----定义一个Hero,为其添加标签,两个标签相同,则可以共享       tag: 'user-head',       child: Padding(         padding: EdgeInsets.all(16.0),         child: CircleAvatar(           backgroundColor: Colors.transparent,           radius: 72.0,           backgroundImage: AssetImage(             "images/mani.jpg",           ),         ),       ),     );     var touch=InkWell(onTap: (){       Navigator.of(context).pop();     },child: hero,);     return Scaffold(       appBar: AppBar(leading:touch ,),       body: Container(         decoration: BoxDecoration(             gradient: LinearGradient(colors: [Colors.red.withAlpha(99),Colors.yellow.withAlpha(189),Colors.green.withAlpha(88),Colors.blue.withAlpha(230)])         ),       ),     );   } } 复制代码

关于createRectTween属性

在回调中会给两个初始和结束的两个矩形,可以进行矩形动画来控制共享组件的区域,如下图在目标页:



16cea9924d620126?imageslim



var height=MediaQuery.of(context).size.height; var width=MediaQuery.of(context).size.width; var size=min(height,width);  var hero=Hero(//----定义一个Hero,为其添加标签,两个标签相同,则可以共享       createRectTween: ((r1,r2){         return RectTween(begin: Rect.fromLTWH(size/2,0, size, size),end:  r2);       }), 复制代码

另外还有个要点:同一页面不能出现多处同名Hero


福利时间:路由动画工具

使用方法看上面的路由跳转处,当然你也可以根据下面的定制更酷炫的跳转效果。

import 'package:flutter/cupertino.dart'; //缩放路由动画 class ScaleRouter<T> extends PageRouteBuilder<T> {   final Widget child;   final int duration_ms;   final Curve curve;   ScaleRouter({this.child, this.duration_ms = 500,this.curve=Curves.fastOutSlowIn})       : super(     pageBuilder: (context, animation, secondaryAnimation) => child,     transitionDuration: Duration(milliseconds: duration_ms),     transitionsBuilder: (context, a1, a2, child) =>         ScaleTransition(           scale: Tween(begin: 0.0, end: 1.0).animate(               CurvedAnimation(parent: a1, curve: curve)),           child: child,         ),   ); } //渐变透明路由动画 class FadeRouter<T> extends PageRouteBuilder<T> {   final Widget child;   final int duration_ms;   final Curve curve;   FadeRouter({this.child, this.duration_ms = 500,this.curve=Curves.fastOutSlowIn})       : super(       pageBuilder: (context, animation, secondaryAnimation) => child,       transitionDuration: Duration(milliseconds: duration_ms),       transitionsBuilder: (context, a1, a2, child) =>           FadeTransition(             opacity: Tween(begin: 0.1, end: 1.0).animate(                 CurvedAnimation(parent: a1, curve:curve,)),             child: child,           )); } //旋转路由动画 class RotateRouter<T> extends PageRouteBuilder<T> {   final Widget child;   final int duration_ms;   final Curve curve;   RotateRouter({this.child, this.duration_ms = 500,this.curve=Curves.fastOutSlowIn})       : super(       pageBuilder: (context, animation, secondaryAnimation) => child,       transitionDuration: Duration(milliseconds: duration_ms),       transitionsBuilder: (context, a1, a2, child) =>           RotationTransition(             turns: Tween(begin: 0.1, end: 1.0).animate(                 CurvedAnimation(parent: a1, curve:curve,)),             child: child,           )); } //右--->左 class Right2LeftRouter<T> extends PageRouteBuilder<T> {   final Widget child;   final int duration_ms;   final Curve curve;   Right2LeftRouter({this.child,this.duration_ms=500,this.curve=Curves.fastOutSlowIn})       :super(       transitionDuration:Duration(milliseconds: duration_ms),       pageBuilder:(ctx,a1,a2){return child;},       transitionsBuilder:(ctx,a1,a2,Widget child,) {         return SlideTransition(             position: Tween<Offset>(               begin: Offset(1.0, 0.0), end: Offset(0.0, 0.0),).animate(                 CurvedAnimation(parent: a1, curve: curve)),             child:  child         );       }); } //左--->右 class Left2RightRouter<T> extends PageRouteBuilder<T> {   final Widget child;   final int duration_ms;   final Curve curve;   List<int> mapper;   Left2RightRouter({this.child,this.duration_ms=500,this.curve=Curves.fastOutSlowIn})       :assert(true),super(       transitionDuration:Duration(milliseconds: duration_ms),       pageBuilder:(ctx,a1,a2){return child;},       transitionsBuilder:(ctx,a1,a2,Widget child,) {         return SlideTransition(             position: Tween<Offset>(               begin: Offset(-1.0, 0.0), end: Offset(0.0, 0.0),).animate(                 CurvedAnimation(parent: a1, curve: curve)),             child:  child         );       }); } //上--->下 class Top2BottomRouter<T> extends PageRouteBuilder<T> {   final Widget child;   final int duration_ms;   final Curve curve;   Top2BottomRouter({this.child,this.duration_ms=500,this.curve=Curves.fastOutSlowIn})       :super(       transitionDuration:Duration(milliseconds: duration_ms),       pageBuilder:(ctx,a1,a2){return child;},       transitionsBuilder:(ctx,a1,a2,Widget child,) {         return SlideTransition(             position: Tween<Offset>(               begin: Offset(0.0,-1.0), end: Offset(0.0, 0.0),).animate(                 CurvedAnimation(parent: a1, curve: curve)),             child:  child         );       }); } //下--->上 class Bottom2TopRouter<T> extends PageRouteBuilder<T> {   final Widget child;   final int duration_ms;   final Curve curve;   Bottom2TopRouter({this.child,this.duration_ms=500,this.curve=Curves.fastOutSlowIn})       :super(       transitionDuration:Duration(milliseconds: duration_ms),       pageBuilder:(ctx,a1,a2){return child;},       transitionsBuilder:(ctx,a1,a2,Widget child,) {         return SlideTransition(             position: Tween<Offset>(               begin: Offset(0.0, 1.0), end: Offset(0.0, 0.0),).animate(                 CurvedAnimation(parent: a1, curve: curve)),             child:  child         );       }); } //缩放+透明+旋转路由动画 class ScaleFadeRotateRouter<T> extends PageRouteBuilder<T> {   final Widget child;   final int duration_ms;   final Curve curve;   ScaleFadeRotateRouter({this.child, this.duration_ms = 500,this.curve=Curves.fastOutSlowIn}) : super(       transitionDuration: Duration(milliseconds: duration_ms),       pageBuilder: (ctx, a1, a2)=>child,//页面       transitionsBuilder: (ctx, a1, a2, Widget child,) {//构建动画         return RotationTransition(//旋转动画           turns: Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(             parent: a1,             curve: curve,           )),           child: ScaleTransition(//缩放动画             scale: Tween(begin: 0.0, end: 1.0).animate(                 CurvedAnimation(parent: a1, curve: curve)),             child: FadeTransition(opacity://透明度动画             Tween(begin: 0.5, end: 1.0).animate(CurvedAnimation(parent: a1, curve: curve)),               child: child,),           ),         );       }); } //无动画 class NoAnimRouter<T> extends PageRouteBuilder<T> {   final Widget page;   NoAnimRouter(this.page)       : super(       opaque: false,       pageBuilder: (context, animation, secondaryAnimation) => page,       transitionDuration: Duration(milliseconds: 0),       transitionsBuilder:           (context, animation, secondaryAnimation, child) => child); } 复制代码
结语

本文到此接近尾声了,如果想快速尝鲜Flutter,《Flutter七日》会是你的必备佳品;如果想细细探究它,那就跟随我的脚步,完成一次Flutter之旅。




点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
移动开发工程师
手记
粉丝
20
获赞与收藏
56

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消