Flutter Hero动画开发实用教程

Posted by manbetx客户端应用下载 on April 21, 2019

Flutter 动画开发实用教程

为大家倾力打造的课程《Flutter从入门到进阶-实战携程网App》上线了,解锁Flutter开发新姿势,一网打尽Flutter核心技术 点我Get!!!

在这篇文章中,将向大家分享Flutter动画中的重要一员Hero动画,以及一些Hero动画的开发技巧和经验

  • 在大家Flutter开发环境过程中遇到无法解决的问题可以在课程问答区进行提问,课程老师会对你进行辅导和帮助;

精心设计的动画会让用户界面感觉更直观、流畅,能改善用户体验。 Flutter的动画支持可以轻松实现各种动画类型。许多widget,特别是Material Design widgets, 都带有在其设计规范中定义的标准动画效果,但也可以自定义这些效果,在开始学习之前呢,我们先来快速过一下本篇文章的目录:

目录

什么是Hero动画?

在 Flutter中可以用 Hero widget创建这个动画。当 Hero 通过动画从源页面飞到目标页面时,目标页面逐渐淡入视野。通常, Hero 是用户界面的一小部分,如图片,它通常在两个页面都有。从用户的角度来看, Hero 在页面之间“飞翔”。接下来我们一起来学习如何创建Hero动画:

实现标准Hero动画

Standard-Hero-Animation

... class PhotoHero extends StatelessWidget { const PhotoHero({ Key key, this.photo, this.onTap, this.width }) : super(key: key); final String photo; final VoidCallback onTap; final double width; Widget build(BuildContext context) { return SizedBox( width: width, child: Hero( tag: photo, child: Material( color: Colors.transparent, child: InkWell( onTap: onTap, child: Image.network( photo, fit: BoxFit.contain, ), ), ), ), ); } } class HeroAnimation extends StatelessWidget { Widget build(BuildContext context) { timeDilation = 10.0; // 1.0 means normal animation speed. return Scaffold( appBar: AppBar( title: const Text('Basic Hero Animation'), ), body: Center( child: PhotoHero( photo: 'https://boke.nrnlibrary.com/flutter/website/master/examples/_animation/Hero_animation/images/flippers-alpha.png', width: 300.0, onTap: () { Navigator.of(context).push(MaterialPageRoute<void>( builder: (BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Flippers Page'), ), body: Container( // Set background to blue to emphasize that it's a new route. color: Colors.lightBlueAccent, padding: const EdgeInsets.all(16.0), alignment: Alignment.topLeft, child: PhotoHero( photo: 'https://boke.nrnlibrary.com/flutter/website/master/examples/_animation/Hero_animation/images/flippers-alpha.png', width: 100.0, onTap: () { Navigator.of(context).pop(); }, ), ), ); } )); }, ), ), ); } } ... 

Hero的函数原型

 const Hero({ Key key, @required this.tag, this.createRectTween, this.flightShuttleBuilder, this.placeholderBuilder, this.transitionOnUserGestures = false, @required this.child, }) : assert(tag != null), assert(transitionOnUserGestures != null), assert(child != null), super(key: key); 
  • tag:[必须]用于关联两个Hero动画的标识;
  • createRectTween:[可选]定义目标Hero的边界,在从起始位置到目的位置的“飞行”过程中该如何变化;
  • child:[必须]定义动画所呈现的widget;

实现径向Hero动画

Radial-Hero-Animation

... class RadialExpansionDemo extends StatelessWidget { static const double kMinRadius = 32.0; static const double kMaxRadius = 128.0; static const opacityCurve = const Interval(0.0, 0.75, curve: Curves.fastOutSlowIn); static RectTween _createRectTween(Rect begin, Rect end) { return MaterialRectCenterArcTween(begin: begin, end: end); } static Widget _buildPage(BuildContext context, String imageName, String description) { return Container( color: Theme.of(context).canvasColor, child: Center( child: Card( elevation: 8.0, child: Column( mainAxisSize: MainAxisSize.min, children: [ SizedBox( width: kMaxRadius * 2.0, height: kMaxRadius * 2.0, child: Hero( createRectTween: _createRectTween, tag: imageName, child: RadialExpansion( maxRadius: kMaxRadius, child: Photo( photo: imageName, onTap: () { Navigator.of(context).pop(); }, ), ), ), ), Text( description, style: TextStyle(fontWeight: FontWeight.bold), textScaleFactor: 3.0, ), const SizedBox(height: 16.0), ], ), ), ), ); } Widget _buildHero(BuildContext context, String imageName, String description) { return Container( width: kMinRadius * 2.0, height: kMinRadius * 2.0, child: Hero( createRectTween: _createRectTween, tag: imageName, child: RadialExpansion( maxRadius: kMaxRadius, child: Photo( photo: imageName, onTap: () { Navigator.of(context).push( PageRouteBuilder<void>( pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) { return AnimatedBuilder( animation: animation, builder: (BuildContext context, Widget child) { return Opacity( opacity: opacityCurve.transform(animation.value), child: _buildPage(context, imageName, description), ); } ); }, ), ); }, ), ), ), ); } @override Widget build(BuildContext context) { timeDilation = 5.0; // 1.0 is normal animation speed. return Scaffold( appBar: AppBar( title: const Text('Radial Transition Demo'), ), body: Container( padding: const EdgeInsets.all(32.0), alignment: FractionalOffset.bottomLeft, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ _buildHero(context, 'https://boke.nrnlibrary.com/flutter/website/master/examples/_animation/radial_Hero_animation/images/chair-alpha.png', 'Chair'), _buildHero(context, 'https://boke.nrnlibrary.com/flutter/website/master/examples/_animation/radial_Hero_animation/images/binoculars-alpha.png', 'Binoculars'), _buildHero(context, 'https://boke.nrnlibrary.com/flutter/website/master/examples/_animation/radial_Hero_animation/images/beachball-alpha.png', 'Beach ball'), ], ), ), ); } } ... 

点我查看全部完整代码

  • 本节学习过程中遇到无法解决的问题可以在课程问答区进行提问,课程老师会对你进行辅导和帮助;
  • 欢迎加入课程官方群:795410523 和讲师以及其他师兄弟们一起学习交流;

参考资料