首页 > 建站教程 > APP开发,混合APP >  Flutter笔记74:Hero页面切换动画正文

Flutter笔记74:Hero页面切换动画

一、Hero Widget
    在某些场景下我们可能需要通过图片进行页面的转场,这种场景在大众点评等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);
        },
      ),
    );
  }
}