在某些场景下我们可能需要通过图片进行页面的转场,这种场景在大众点评等APP上非常常见,Feed 流中有图片,点击之后,通过图片进行页面的转场
进行转场,就需要两个页面,一个页面的图片触发跳转,另一个页面用来承接这次的跳转
Hero Widget 则是在页面中用来关联两个页面的桥梁
当然,这个过程中,在页面返回的时候, 后置页面变成前置页面,Hero Widget 则将动画 reverse 执行一次
Hero Widget 构造函数如下:
const Hero({ Key key, @required this.tag, this.createRectTween, this.flightShuttleBuilder, this.placeholderBuilder, this.transitionOnUserGestures = false, @required this.child, })其中 tag 和 child 是 @required 的属性
tag 是两个 Hero 的之间相同标识,两个 Hero Widget 通过 tag 关联在一起
二、Hero Widget 跳转页面
下面代码中,将 Hero 放在了 GestureDetector 中,点击的时候打开新的页面。
注意,在导航跳转的时候,fullscreenDialog 我设置的属性时 false(这里注释了)
Hero 的 tag 中使用的是 imgHero,这应该是一个唯一的标识,而 child 直接放了一张图片
GestureDetector( child: Hero( tag: 'imgHero', child: Image.network( IMAGE_SRC, fit: BoxFit.cover, width: 300, ), ), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (_) => NewPage(), // settings: RouteSettings(isInitialRoute: true), // fullscreenDialog: true, ), ); }, )三、Hero 承接页面
为了能够承接住之前的页面,在下一跳页面中的 Hero 组件中,也应该设置 tag 是 imgHero
child: GestureDetector( child: Hero( tag: 'imgHero', child: Image.network( IMAGE_SRC, fit: BoxFit.cover, ), ), onTap: () { Navigator.pop(context); }, ),四、各种特殊情况
1、如果 Hero 的 tag 不匹配会怎样?
如果两个页面的 Hero 的 tag 不匹配,则无法承接住转场动画,就会变成普通的打开页面
2、如果 Hero 的 child 不是图片会怎样?
转场动画的承接与图片是无关的,比如下面代码中使用一个 Container 也没问题
child: Hero( tag: 'imgHero', child: Container( width: 300, height: 300, color: Colors.pink, ), )3、两个 Hero 的 child 不一致会怎样?
只要 tag 能够匹配,与 Hero 承载内容不同
五、Hero简单的转场动画代码:
import 'package:flutter/material.dart'; class HeroAnimation extends StatelessWidget{ @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('页面一'), ), body: GestureDetector( child: Hero( tag: '第一张图片', child: Image.network('http://www.5imoban.net/uploads/allimg/200619/1-200619222R40-L.jpg') ), onTap: (){ Navigator.push(context, MaterialPageRoute(builder: (_){ return NextPage(); })); }, ), ); } } class NextPage extends StatelessWidget{ @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('页面二'), ), body: GestureDetector( child: Hero( tag: '第二张图片', child: Image.network('http://www.5imoban.net/uploads/allimg/200414/1-2004142140050-L.jpg') ), onTap: (){ Navigator.pop(context); }, ), ); } }