当前位置: 首页 > news >正文

Flutter Hero Animation 详解

Flutter Hero Animation 详解

一、Hero Animation 概述

Hero Animation(英雄动画)是 Flutter 中用于页面间共享元素过渡的动画效果。它可以让同一个元素在两个页面之间平滑过渡。

1.1 基本概念

  • Hero Widget- 标记为英雄的组件
  • Hero Tag- 唯一标识符,用于匹配两个页面的英雄组件
  • Flight- 英雄组件从源页面飞到目标页面的过程

二、基本用法

2.1 源页面

class SourcePage extends StatelessWidget { const SourcePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('源页面')), body: Center( child: GestureDetector( onTap: () { Navigator.push( context, MaterialPageRoute(builder: (_) => const TargetPage()), ); }, child: const Hero( tag: 'imageHero', child: Image( image: AssetImage('assets/image.jpg'), width: 100, height: 100, ), ), ), ), ); } }

2.2 目标页面

class TargetPage extends StatelessWidget { const TargetPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('目标页面')), body: const Center( child: Hero( tag: 'imageHero', child: Image( image: AssetImage('assets/image.jpg'), width: 300, height: 300, ), ), ), ); } }

三、自定义 Hero 动画

3.1 使用 HeroController

class CustomHeroController extends HeroController { @override Animation<double> createHeroFlightAnimation( HeroFlightDirection direction, Animation<double> overallAnimation, Hero hero, BuildContext context, ) { return CurvedAnimation( parent: overallAnimation, curve: direction == HeroFlightDirection.push ? Curves.easeOut : Curves.easeIn, ); } }

3.2 使用 flightShuttleBuilder

Hero( tag: 'customHero', flightShuttleBuilder: ( BuildContext flightContext, Animation<double> animation, HeroFlightDirection flightDirection, BuildContext fromHeroContext, BuildContext toHeroContext, ) { return ScaleTransition( scale: animation, child: const Image(image: AssetImage('assets/image.jpg')), ); }, child: const Image(image: AssetImage('assets/image.jpg')), )

3.3 使用 placeholderBuilder

Hero( tag: 'placeholderHero', placeholderBuilder: (context, heroSize, child) { return Container( width: heroSize.width, height: heroSize.height, color: Colors.grey[200], child: const CircularProgressIndicator(), ); }, child: const Image(image: AssetImage('assets/image.jpg')), )

四、实战案例

4.1 图片画廊

class GalleryPage extends StatelessWidget { const GalleryPage({super.key}); @override Widget build(BuildContext context) { return GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, crossAxisSpacing: 8, mainAxisSpacing: 8, ), itemCount: 9, itemBuilder: (context, index) { return GestureDetector( onTap: () { Navigator.push( context, PageRouteBuilder( pageBuilder: (_, __, ___) => DetailPage(index: index), transitionsBuilder: (_, animation, __, child) { return FadeTransition( opacity: animation, child: child, ); }, ), ); }, child: Hero( tag: 'gallery-$index', child: Image.network( 'https://picsum.photos/200/200?random=$index', fit: BoxFit.cover, ), ), ); }, ); } }

4.2 卡片详情过渡

class CardDetailPage extends StatelessWidget { final int index; const CardDetailPage({super.key, required this.index}); @override Widget build(BuildContext context) { return Scaffold( body: CustomScrollView( slivers: [ SliverAppBar( expandedHeight: 300, flexibleSpace: FlexibleSpaceBar( background: Hero( tag: 'card-image-$index', child: Image.network( 'https://picsum.photos/600/400?random=$index', fit: BoxFit.cover, ), ), ), ), const SliverToBoxAdapter( child: Padding( padding: EdgeInsets.all(16), child: Text('卡片详情内容...'), ), ), ], ), ); } }

4.3 多个 Hero 动画

// 源页面 Row( children: [ Hero( tag: 'avatar', child: const CircleAvatar(radius: 40), ), const SizedBox(width: 16), Hero( tag: 'name', child: const Text('用户名'), ), ], ) // 目标页面 Column( children: [ Hero( tag: 'avatar', child: const CircleAvatar(radius: 80), ), const SizedBox(height: 16), Hero( tag: 'name', child: const Text('用户名', style: TextStyle(fontSize: 24)), ), ], )

五、性能优化

5.1 使用 RepaintBoundary

Hero( tag: 'complexHero', child: RepaintBoundary( child: const ComplexWidget(), ), )

5.2 避免复杂 Widget

// 不好:复杂 Widget 作为 Hero 子组件 Hero( tag: 'badHero', child: Container( child: Column( children: [/* 很多子组件 */], ), ), ) // 好:简化子组件 Hero( tag: 'goodHero', child: const Image(image: AssetImage('assets/image.jpg')), )

六、总结

Hero Animation 是页面过渡的强大工具:

  1. 基本用法- 使用 Hero Widget 和相同的 tag
  2. 自定义动画- flightShuttleBuilder、placeholderBuilder
  3. 多 Hero- 同时过渡多个元素
  4. 性能优化- 使用 RepaintBoundary、简化子组件

合理使用 Hero 动画可以提升用户体验。

http://www.rkmt.cn/news/1424323.html

相关文章:

  • 2026年Q2北京铝合金回收:北京溴化锂机组回收/北京电器回收/北京电子设备回收/北京电池回收/北京电线电缆回收/选择指南 - 优质品牌商家
  • 【图像提取】基于数学形态学的数字视网膜图像血管提取 (DRIVE) 数据集分割附Matlab代码
  • 【AI搜索革命性差异指南】:3大核心维度拆解AI搜索与传统搜索的底层逻辑差异
  • 【绿化】Fong投屏 一键手机投屏 多设备兼容超稳定
  • 深入Windows消息循环:手把手教你用Unity拦截WM_SIZING实现自定义窗口控制
  • 如何选择工程信息平台?2026年5月推荐口碑好的服务项目人脉难寻痛点 - 品牌推荐
  • 5分钟终结VC运行库安装难题:一站式解决方案深度解析
  • Lindy内容创作自动化:从零搭建抗衰减内容引擎的4层架构,含GitHub开源模板
  • Linux系统终极解决方案:Dislocker轻松访问BitLocker加密分区
  • AMBA 总线接口访问明细
  • Agent赋能下药物警戒自动生成的个例报告符合监管要求吗?深度拆解AI Agent在PV领域的合规边界
  • 178、运动控制中的行业标准:功能安全IEC 61508
  • 技术人的个人理财:从入门到精通
  • 微信聊天记录永久保存完整指南:WeChatExporter开源工具使用教程
  • 从零开发游戏需要学习的c#模块,第三十一章(技能冷却系统 —— 范围爆炸)
  • DroidCam OBS插件终极指南:让手机摄像头快速变身高清直播源
  • 3个核心功能彻底解决Windows C盘爆红问题:开源工具Windows Cleaner深度解析
  • 微信视频号直播数据抓取终极指南:5分钟搭建专业级监控系统
  • Prompt Engineering 深度解析:从 Few-shot 到结构化提示的系统化方法
  • 基于STM32的多功能万年历电子闹钟设计与实现
  • 从“事后Debug”到“事前防御”:聊聊C#代码契约(Code Contracts)与Assert断言的配合使用
  • 2025-2026年全球留香沐浴露品牌推荐:十大口碑产品评测约会前提升魅力价格注意事项 - 品牌推荐
  • ROS2跨机通信真就这么简单?用DDS和ROS_DOMAIN_ID轻松隔离你的机器人网络
  • 专业级AVIF图像插件:Photoshop高效图像压缩完整解决方案
  • AI 模型推理服务部署深度解析:从 Triton 到 vLLM 的生产级推理架构
  • 你的Zotero文献语言设置对了吗?GB/T 7714样式下,让英文文献正确显示‘et al.’的完整配置流程
  • 如何选留香沐浴露品牌?2026年5月推荐TOP10对比香气持久案例适用场景 - 品牌推荐
  • 国民技术N32G430双分区(Boot+App)IAP项目实战:Makefile编译与pyOCD烧录全解析
  • 2025-2026年留香沐浴露品牌推荐:十大口碑产品评测卧室安睡香氛助眠市场份额价格 - 品牌推荐
  • 别再只画堆叠图了!用Seurat+ggplot2搞定单细胞比例统计与组间差异分析(附完整代码)