【Flutter】Hero 动画 ( Hero 实现径向动画 | Hero 组件 createRectTween 设置 )(一)

简介: 【Flutter】Hero 动画 ( Hero 实现径向动画 | Hero 组件 createRectTween 设置 )(一)

文章目录

◯、Hero 构造函数

一、圆形方形组件

二、创建页面 1 的组件 ( Hero 组件 1 )

三、创建页面 2 的组件 ( Hero 组件 2 )

四、完整代码示例

五、相关资源





◯、Hero 构造函数


Hero 构造函数 :


 

/// 创建一个 Hero 组件 ;
  ///
  /// tag , child 参数不能为空 ; 
  /// child 参数的值不能是 Hero 组件以及 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);


required this.tag : 不能为空 , 用于 关联两个界面的 Hero 组件 , 两个 Hero 组件有关联关系 , 则设置相同的 tag 字符串 ;


this.createRectTween : 可以为空 , 用于 定义 Hero 组件的边界 , 以及定义 Hero 组件在界面切换时 , 从 源界面的起始位置 到 目的界面的最终位置 , 动画执行的变化过程 ;


required this.child : 不能为空 , 普通的 Widget 组件 , Hero 动画作用的组件 ;



Hero 动画可以实现径向动画 , 径向动画指的是组件形状可变的动画 , 如圆形变方形 , 方形变三角形 ;


Hero 径向动画 与 普通动画的区别就是是否设置了 createRectTween 参数 ;






一、圆形方形组件


圆形方形变化的组件 : 该组件可以根据不同的参数实现圆形到方形的变化 , 或方形到圆形的变化 ;


/// Hero 组件 , 径向动画扩展
/// 该组件主要用于裁剪组件用的
class OvalRectWidget extends StatelessWidget {
  /// 这里的裁剪大小 clipRectSize 最大半径 / 2 的开方值 再乘以 2
  const OvalRectWidget({Key key, this.maxRadius, this.child})
      : clipRectSize = 2.0 * (maxRadius / math.sqrt2),
        super(key: key);
  // 最大半径值
  final double maxRadius;
  /// 该值需要动态计算
  final clipRectSize;
  final Widget child;
  /// 这里特别注意该圆形裁剪组件
  /// 如果整个组件的宽高都是 maxRadius ,
  /// 内部的方形组件宽高是 2.0 * (maxRadius / math.sqrt2)
  /// 并且该方形组件居中显示
  /// 那么该方形组件的四个顶点正好处于圆形组件的裁剪半径位置
  /// 也就是方形组件完整显示 , 没有裁剪到
  @override
  Widget build(BuildContext context) {
    /// 布局裁剪组件 , 可以将布局裁剪成圆形
    return ClipOval(
      /// 可用于约束布局大小的组件
      /// 这里的居中显示是关键 , 如果不居中显示 , 最终还是圆形
      child: Center(
        child: SizedBox(
          width: clipRectSize,
          height: clipRectSize,
          /// 用于裁剪圆角矩形的组件
          child: ClipRect(
            child: child,
          ),
        ),
      ),
    );
  }
}



组件形状显示分析 :


① 方形裁剪组件 : ClipOval 组件区域是 红色 矩形所在位置 , 其裁剪区域是蓝色组件位置 , 如果正好有个方形的组件 ClipRect 处于下面橙色区域内 , 那么该方形组件正好躲过了被外围红色区域 ClipOval 裁剪的操作 ; 显示的仍然是方形的组件 ;

image.png



② 圆形裁剪组件 : 如果 ClipOval 圆形裁剪组件 ( 红色 ) 与 ClipRect 方形的裁剪组件 ( 橙色 ) 位置重叠 , 那么该方形的裁剪组件肯定就被裁剪成圆形的了 ;

image.png



上面两个组件就是 Hero 径向动画的主要作用组件 , 该动画执行前 , 组件是圆形的 , 执行后组件是方形的 , 这就是改变了外层的 ClipOval 组件的大小 , 导致形状改变 ;






二、创建页面 1 的组件 ( Hero 组件 1 )


页面 1 的 Hero 组件显示的圆形的 , 跳转到页面 2 后 , 相同 tag 的 Hero 组件显示方形 ;


控制 OvalRectWidget 是圆形还是方形 , 主要是控制 OvalRectWidget 组件的宽高 , 这里设置的宽高设置 , 相当于上面的 " ② 圆形裁剪组件 " 情况 , 整个组件被裁剪成圆形的组件 ;


创建页面 1 的组件 :


/// 创建在界面 1 显示的图标 , 点击后跳转到界面 2
  /// 页面的核心组件是 Hero 组件 , 而且是 3 个
  Widget _buildFirstPagWidget(
      BuildContext context, String imageName, String description) {
    return Container(
      /// 界面 1 中的显示的 Hero 组件是小图标
      /// 图标大小就是半径的两倍
      width: minRadius * 2.0,
      height: minRadius * 2.0,
      /// 主界面的核心 Hero 动画
      child: Hero(
        /// 这是 Hero 径向动画与标准 Hero 动画的区别
        /// 如果没有这个动画 , 中间过程会变成椭圆
        createRectTween: _createRectTween,
        /// Hero 动画标签
        tag: imageName,
        child: OvalRectWidget(
          maxRadius: maxRadius,
          /// 最内层显示的是网络图片组件
          child: ImageWidget(
            /// 设置网络图片地址
            imageUrl: imageName,
            // 设置点击事件
            onTap: () {
              /// 点击后跳转到新界面中
              Navigator.of(context).push(PageRouteBuilder<void>(pageBuilder:
                  (BuildContext context, Animation<double> animation,
                      Animation<double> secondaryAnimation) {
                // 创建一个 RoutePageBuilder
                return AnimatedBuilder(
                    animation: animation,
                    builder: (context, child) {
                      /// 设置透明度组件
                      return Opacity(
                        /// 当前的透明度值 , 取值 0.0 ~ 1.0
                        opacity: opacityCurve.transform(animation.value),
                        // 主要显示的使用透明度控制的组件
                        // 页面 2 组件
                        child: _buildSecondPageWidget(context, imageName, description),
                      );
                    });
              }));
            },
          ),
        ),
      ),
    );
  }




三、创建页面 2 的组件 ( Hero 组件 2 )


页面 1 的 Hero 组件显示的圆形的 , 跳转到页面 2 后 , 相同 tag 的 Hero 组件显示方形 ;


控制 OvalRectWidget 是圆形还是方形 , 主要是控制 OvalRectWidget 组件的宽高 , 这里设置的宽高相当于上面的 " ① 方形裁剪组件 " 设置 , 整个组件没有被裁剪到 , 显示的是方形组件 ;


创建页面 2 的组件 :


/// 创建页面 2 , 这是点击后跳转到的页面
  /// 三个参数分别是 : 上下文 , 图片名称 , 页面描述
  /// 页面的核心组件是 Hero 组件 , 只有 1 个
  static Widget _buildSecondPageWidget(
      BuildContext context, String imageName, String description) {
    return Container(
      color: Theme.of(context).canvasColor,
      child: Center(
        child: Card(
          /// 设置卡片布局阴影大小
          elevation: 8,
          /// 卡片布局中显示图片和图片的描述
          child: Column(
            /// 在主轴方向 , 也就是垂直方向 , 应该占用多少空间
            /// Colum 主轴方向是垂直方向
            /// Row 主轴方向是水平方向
            mainAxisSize: MainAxisSize.min,
            children: [
              SizedBox(
                /// 约束布局大小的组件的宽高定义为最大半径的两倍
                width: maxRadius * 2,
                height: maxRadius * 2,
                /// 核心 Hero 组件
                child: Hero(
                  /// 创建径向动画
                  /// 如果没有这个动画 , 中间过程会变成椭圆
                  createRectTween: _createRectTween,
                  /// Hero 动画标签 ID
                  tag: imageName,
                  /// Hero 动画作用的组件
                  child: OvalRectWidget(
                    /// 这里的半径设置为最大半径值 ,
                    maxRadius: maxRadius,
                    /// 最内层显示的是网络图片组件
                    child: ImageWidget(
                      imageUrl: imageName,
                      onTap: () {
                        /// 点击后关闭当前页面
                        Navigator.of(context).pop();
                      },
                    ),
                  ),
                ),
              ),
              /// 图片描述文本
              Text(
                // 设置文本内容
                description,
                // 设置文本样式, 粗体
                style: TextStyle(fontWeight: FontWeight.bold),
                textScaleFactor: 3.0,
              ),
              /// 空白间隔 , 无实际意义
              const SizedBox(
                height: 16,
              ),
            ],
          ),
        ),
      ),
    );
  }


目录
相关文章
|
前端开发 安全 开发工具
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
798 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
Dart 前端开发
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
479 75
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
Dart 前端开发 容器
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
460 18
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
前端开发 Java 开发工具
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
1221 18
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
|
11月前
|
索引
【Flutter 开发必备】AzListView 组件全解析,打造丝滑索引列表!
在 Flutter 开发中,AzListView 是实现字母索引分类列表的理想选择。它支持 A-Z 快速跳转、悬浮分组标题、自定义 UI 和高效性能,适用于通讯录、城市选择等场景。本文将详细解析 AzListView 的核心参数和实战示例,助你轻松实现流畅的索引列表。
547 7
|
开发工具 UED 容器
Flutter&鸿蒙next 实现长按录音按钮及动画特效
本文介绍了如何在 Flutter 中实现一个带有动画效果的长按录音按钮。通过使用 `GestureDetector` 监听长按手势,结合 `AnimatedContainer` 和 `AnimationController` 实现按钮的动画效果,以及 `flutter_sound` 插件完成录音功能。文章详细讲解了功能需求、实现思路和代码实现,帮助读者逐步掌握这一实用功能的开发方法。
594 5
Flutter 自定义组件继承与调用的高级使用方式
本文深入探讨了 Flutter 中自定义组件的高级使用方式,包括创建基本自定义组件、继承现有组件、使用 Mixins 和组合模式等。通过这些方法,您可以构建灵活、可重用且易于维护的 UI 组件,从而提升开发效率和代码质量。
459 1
|
开发工具
Flutter&鸿蒙next中封装一个列表组件
Flutter&鸿蒙next中封装一个列表组件
247 0
|
Dart Android开发
【Flutter】StatefulWidget 组件 ( 创建 StatefulWidget 组件 | MaterialApp 组件 | Scaffold 组件 )(一)
【Flutter】StatefulWidget 组件 ( 创建 StatefulWidget 组件 | MaterialApp 组件 | Scaffold 组件 )(一)
280 0
【Flutter】StatefulWidget 组件 ( 创建 StatefulWidget 组件 | MaterialApp 组件 | Scaffold 组件 )(一)
|
Dart 开发者
【Flutter】StatefulWidget 组件 ( 创建 StatefulWidget 组件 | MaterialApp 组件 | Scaffold 组件 )(二)
【Flutter】StatefulWidget 组件 ( 创建 StatefulWidget 组件 | MaterialApp 组件 | Scaffold 组件 )(二)
343 0

热门文章

最新文章