1. Flutter Hero动画开发实用教程

              Posted by 本的秘密博客 on April 21, 2019

              Flutter 动画开发实用教程

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

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

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

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

              目录

              • 什么是Hero动画?
              • 如何实现标准Hero动画?
              • Hero的函数原型的函数原型是什么?
              • 如何实现径向Hero动画?

              什么是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://raw.githubusercontent.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://raw.githubusercontent.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://raw.githubusercontent.com/flutter/website/master/examples/_animation/radial_Hero_animation/images/chair-alpha.png', 'Chair'),
                          _buildHero(context, 'https://raw.githubusercontent.com/flutter/website/master/examples/_animation/radial_Hero_animation/images/binoculars-alpha.png', 'Binoculars'),
                          _buildHero(context, 'https://raw.githubusercontent.com/flutter/website/master/examples/_animation/radial_Hero_animation/images/beachball-alpha.png', 'Beach ball'),
                        ],
                      ),
                    ),
                  );
                }
              }
              ...
              

              点我查看全部完整代码

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

              参考资料



              16kou fushipifaw 1sysb 155217 293182 618632 229187 266793 782276 177152 598613 536683 658753 218325 896853 596113 675327 021sh6 278857 0551tt 0752cy 022ct ahcnjt 52lpw