前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Flutter】Hero 动画 ( Hero 动画使用流程 | 创建 Hero 动画核心组件 | 创建源页面 | 创建目的页面 | 页面跳转 )

【Flutter】Hero 动画 ( Hero 动画使用流程 | 创建 Hero 动画核心组件 | 创建源页面 | 创建目的页面 | 页面跳转 )

作者头像
韩曙亮
发布2023-03-29 09:11:46
8650
发布2023-03-29 09:11:46
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

◯、Hero 动画简介


Hero Widget 动画效果 : Hero 通过动画从 源界面 运动到 目标界面 时 , 目标界面 透明度逐渐增加 , 淡入显示 ;

Hero 是界面的组成部分 , 在 源界面 和 目标界面 都存在该组件 ;

Hero 动画涉及到的 API 较多 ;

一、创建 Hero 动画核心组件


Hero 动画 tag 标识 : Hero 动画作用的组件在两个界面中都存在 , 给这两个 Hero 组件都设置相同的标识 , 通过该标识可以标识两个 Hero 组件之间进行动画过渡 ;

该 Hero 动画组件封装内容 :

  • VoidCallback onTap : 从外部传入一个回调事件 , 这是点击组件后 , 回调的函数 ;
  • String imageUrl : 作为 Hero 动画的 tag 标识 , 同时也是图片的 url 网络地址 ;
  • double width : 用于约束 Hero 组件的宽度 ;

代码示例 : 这里定义核心组件 Hero 组件 , 传入 tag 标识 , 与 Hero 动画作用的组件 ;

代码语言:javascript
复制
/// Hero 组件 , 跳转前后两个页面都有该组件
class HeroWidget extends StatelessWidget{
  /// 构造方法
  const HeroWidget({Key key, this.imageUrl, this.width, this.onTap}) : super(key: key);

  /// Hero 动画之间关联的 ID , 通过该标识
  /// 标识两个 Hero 组件之间进行动画过渡
  /// 同时该字符串也是图片的 url 网络地址
  final String imageUrl;
  /// 点击后的回调事件
  final VoidCallback onTap;
  /// 宽度
  final double width;

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: width,

      /// 这里定义核心组件 Hero 组件 , 传入 tag 标识 , 与 Hero 动画作用的组件
      child: Hero(tag: imageUrl, child: Material(
        color: Colors.transparent,
        /// 按钮
        child: InkWell(
          /// 按钮点击事件
          onTap: onTap,
          child: Image.network(imageUrl, fit: BoxFit.contain,),
        ),
      ),),
    );
  }
}

二、创建源页面


创建一个 StatelessWidget 组件作为源页面 , 其中封装 HeroWidget 组件 , 作为显示的核心组件 , 传入一个 VoidCallback 方法 , 在该方法中跳转到目的界面 ;

代码语言:javascript
复制
class HeroAnimation extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    // 时间膨胀系数 , 用于降低动画运行速度
    timeDilation = 10.0;

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Hero 动画演示( 跳转前页面 )"),
        ),
        body: Container(
          color: Colors.white,
          padding: EdgeInsets.all(20),
          alignment: Alignment.bottomRight,
          child: HeroWidget(
            imageUrl: "https://img-blog.csdnimg.cn/20210329101628636.jpg",
            width: 300,
            // 点击事件 , 这里点击该组件后 , 跳转到新页面
            onTap: (){
              
            },
          ),
        ),
      ),
    );
  }
}

三、创建目的页面


创建目的界面 : 这里直接在代码中创建 , 该界面中也封装了 HeroWidget 组件 , 其 tag 与源界面 HeroWidget 组件相同 , 这样就可以保证这两个界面互相跳转时 , 能触发 Hero 动画 ;

代码语言:javascript
复制
MaterialPageRoute(
    builder: (context){
      /// 跳转到的新界面再此处定义
      return MaterialApp(
        home: Scaffold(
          appBar: AppBar(
            title: Text("Hero 动画演示( 跳转后页面 )"),
          ),
          body: Container(
            color: Colors.white,
            padding: EdgeInsets.all(20),
            alignment: Alignment.topLeft,
            child: HeroWidget(
              imageUrl: "https://img-blog.csdnimg.cn/20210329101628636.jpg",
              width: 100,
              onTap: (){
                /// 退出当前界面
                Navigator.of(context).pop();
              },
            ),
          ),
        ),
      );
    }
)

四、页面跳转


使用 Navigator 进行页面跳转 , 这个页面直接在方法中创建出来 ;

代码语言:javascript
复制
Navigator.of(context).push(
    MaterialPageRoute(
        builder: (context){
          /// 跳转到的新界面再此处定义
          return MaterialApp(
            home: Scaffold(
            ),
          );
        }
    )
);

如果出现页面跳转错误 , 参考 【错误记录】Flutter 界面跳转报错 ( Navigator operation requested with a context that does not include a Naviga ) 解决 ;

五、完整代码示例


完整代码示例 :

代码语言:javascript
复制
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart' show timeDilation;

void main() {
  runApp(
    MaterialApp(
      home: HeroAnimation(),
    )
  );
}

/// Hero 组件 , 跳转前后两个页面都有该组件
class HeroWidget extends StatelessWidget{
  /// 构造方法
  const HeroWidget({Key key, this.imageUrl, this.width, this.onTap}) : super(key: key);

  /// Hero 动画之间关联的 ID , 通过该标识
  /// 标识两个 Hero 组件之间进行动画过渡
  /// 同时该字符串也是图片的 url 网络地址
  final String imageUrl;
  /// 点击后的回调事件
  final VoidCallback onTap;
  /// 宽度
  final double width;

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: width,

      /// 这里定义核心组件 Hero 组件 , 传入 tag 标识 , 与 Hero 动画作用的组件
      child: Hero(tag: imageUrl, child: Material(
        color: Colors.transparent,
        /// 按钮
        child: InkWell(
          /// 按钮点击事件
          onTap: onTap,
          child: Image.network(imageUrl, fit: BoxFit.contain,),
        ),
      ),),
    );
  }
}


class HeroAnimation extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    // 时间膨胀系数 , 用于降低动画运行速度
    timeDilation = 10.0;

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Hero 动画演示( 跳转前页面 )"),
        ),
        body: Container(
          color: Colors.white,
          padding: EdgeInsets.all(20),
          alignment: Alignment.bottomRight,
          child: HeroWidget(
            imageUrl: "https://img-blog.csdnimg.cn/20210329101628636.jpg",
            width: 300,
            // 点击事件 , 这里点击该组件后 , 跳转到新页面
            onTap: (){

              print("点击事件触发, 切换到新界面");

              Navigator.of(context).push(
                  MaterialPageRoute(
                      builder: (context){
                        /// 跳转到的新界面再此处定义
                        return MaterialApp(
                          home: Scaffold(
                            appBar: AppBar(
                              title: Text("Hero 动画演示( 跳转后页面 )"),
                            ),
                            body: Container(
                              color: Colors.white,
                              padding: EdgeInsets.all(20),
                              alignment: Alignment.topLeft,
                              child: HeroWidget(
                                imageUrl: "https://img-blog.csdnimg.cn/20210329101628636.jpg",
                                width: 100,
                                onTap: (){
                                  /// 退出当前界面
                                  Navigator.of(context).pop();
                                },
                              ),
                            ),
                          ),
                        );
                      }
                  )
              );
            },
          ),
        ),
      ),
    );
  }
}

运行效果 :

六、相关资源


参考资料 :

重要的专题 :

博客源码下载 :

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-03-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • ◯、Hero 动画简介
  • 一、创建 Hero 动画核心组件
  • 二、创建源页面
  • 三、创建目的页面
  • 四、页面跳转
  • 五、完整代码示例
  • 六、相关资源
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档