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

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

文章目录

◯、Hero 动画简介

一、创建 Hero 动画核心组件

二、创建源页面

三、创建目的页面

四、页面跳转

五、完整代码示例

六、相关资源





◯、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 动画作用的组件 ;


/// 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 方法 , 在该方法中跳转到目的界面 ;


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://ucc.alicdn.com/images/user-upload-01/20210329101628636.jpg",
            width: 300,
            // 点击事件 , 这里点击该组件后 , 跳转到新页面
            onTap: (){
            },
          ),
        ),
      ),
    );
  }
}






三、创建目的页面


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


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://ucc.alicdn.com/images/user-upload-01/20210329101628636.jpg",
              width: 100,
              onTap: (){
                /// 退出当前界面
                Navigator.of(context).pop();
              },
            ),
          ),
        ),
      );
    }
)




四、页面跳转


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


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


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






五、完整代码示例


完整代码示例 :


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://ucc.alicdn.com/images/user-upload-01/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://ucc.alicdn.com/images/user-upload-01/20210329101628636.jpg",
                                width: 100,
                                onTap: (){
                                  /// 退出当前界面
                                  Navigator.of(context).pop();
                                },
                              ),
                            ),
                          ),
                        );
                      }
                  )
              );
            },
          ),
        ),
      ),
    );
  }
}



运行效果 :

image.png







六、相关资源


参考资料 :


Flutter 官网 : https://flutter.dev/

Flutter 插件下载地址 : https://pub.dev/packages

Flutter 开发文档 : https://flutter.cn/docs ( 强烈推荐 )

官方 GitHub 地址 : https://github.com/flutter

Flutter 中文社区 : https://flutter.cn/

Flutter 实用教程 : https://flutter.cn/docs/cookbook

Flutter CodeLab : https://codelabs.flutter-io.cn/

Dart 中文文档 : https://dart.cn/

Dart 开发者官网 : https://api.dart.dev/

Flutter 中文网 : https://flutterchina.club/ , http://flutter.axuer.com/docs/

Flutter 相关问题 : https://flutterchina.club/faq/ ( 入门阶段推荐看一遍 )

GitHub 上的 Flutter 开源示例 : https://download.csdn.net/download/han1202012/15989510

Flutter 实战电子书 : https://book.flutterchina.club/chapter1/


重要的专题 :


Flutter 动画参考文档 : https://flutterchina.club/animations/


博客源码下载 :


GitHub 地址 : https://github.com/han1202012/flutter_animation ( 随博客进度一直更新 , 有可能没有本博客的源码 )


博客源码快照 : https://download.csdn.net/download/han1202012/16188742 ( 本篇博客的源码快照 , 可以找到本博客的源码 )


目录
相关文章
|
5天前
|
存储 调度 数据安全/隐私保护
鸿蒙Flutter实战:13-鸿蒙应用打包上架流程
鸿蒙应用打包上架流程包括创建应用、打包签名和上传应用。首先,在AppGallery Connect中创建项目、APP ID和元服务。接着,使用Deveco进行手动签名,生成.p12和.csr文件,并在AppGallery Connect中上传CSR文件获取证书。最后,配置签名并打包生成.app文件,上传至应用市场。常见问题包括检查签名配置文件是否正确。参考资料:[应用/服务签名](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-signing-V5)。
27 3
鸿蒙Flutter实战:13-鸿蒙应用打包上架流程
|
8天前
|
开发工具 UED 容器
Flutter&鸿蒙next 实现长按录音按钮及动画特效
本文介绍了如何在 Flutter 中实现一个带有动画效果的长按录音按钮。通过使用 `GestureDetector` 监听长按手势,结合 `AnimatedContainer` 和 `AnimationController` 实现按钮的动画效果,以及 `flutter_sound` 插件完成录音功能。文章详细讲解了功能需求、实现思路和代码实现,帮助读者逐步掌握这一实用功能的开发方法。
85 5
|
10天前
Flutter 自定义组件继承与调用的高级使用方式
本文深入探讨了 Flutter 中自定义组件的高级使用方式,包括创建基本自定义组件、继承现有组件、使用 Mixins 和组合模式等。通过这些方法,您可以构建灵活、可重用且易于维护的 UI 组件,从而提升开发效率和代码质量。
110 1
|
10天前
|
前端开发 开发者
深入探索 Flutter 鸿蒙版的画笔使用与高级自定义动画
本文深入探讨了 Flutter 中的绘图功能,重点介绍了 CustomPainter 和 Canvas 的使用方法。通过示例代码,详细讲解了如何绘制自定义图形、设置 Paint 对象的属性以及实现高级自定义动画。内容涵盖基本绘图、动画基础、渐变动画和路径动画,帮助读者掌握 Flutter 绘图与动画的核心技巧。
62 1
|
10天前
|
开发工具 UED
Flutter&鸿蒙next中封装一个输入框组件
本文介绍了如何创建一个简单的Flutter播客应用。首先,通过`flutter create`命令创建项目;接着,在`lib`目录下封装一个自定义输入框组件`CustomInput`;然后,在主应用文件`main.dart`中使用该输入框组件,实现简单的UI布局和功能;最后,通过`flutter run`启动应用。本文还提供了后续扩展建议,如状态管理、网络请求和UI优化。
87 1
|
14天前
|
Dart UED
Flutter用户交互组件
Flutter用户交互组件
17 2
|
16天前
动画控制器在 Flutter 中的工作原理
【10月更文挑战第18天】总的来说,动画控制器 `AnimationController` 在 Flutter 中起着关键的作用,它通过控制动画的数值、速度、节奏和状态,实现了丰富多彩的动画效果。理解它的工作原理对于我们在 Flutter 中创建各种精彩的动画是非常重要的。
|
9天前
|
开发工具
Flutter&鸿蒙next中封装一个列表组件
Flutter&鸿蒙next中封装一个列表组件
21 0
|
28天前
|
UED
flutter:动画&状态管理 (十三)
本文档介绍了Flutter中`animatedList`的使用方法和状态管理的示例。`animatedList`用于创建带有动画效果的列表,示例代码展示了如何添加、删除列表项,并执行相应的动画效果。状态管理部分通过一个简单的点击切换颜色的示例,演示了如何在Flutter中管理组件的状态。
|
1月前
|
Android开发 iOS开发 容器
鸿蒙harmonyos next flutter混合开发之开发FFI plugin
鸿蒙harmonyos next flutter混合开发之开发FFI plugin