当前位置: 首页 > 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.jsqmd.com/news/913013/

相关文章:

  • 2026年Q2北京铝合金回收:北京溴化锂机组回收/北京电器回收/北京电子设备回收/北京电池回收/北京电线电缆回收/选择指南 - 优质品牌商家
  • 从MODBUS协议栈到你的代码:深入理解CRC-16校验的‘位反序’到底在干什么?
  • 高性能语音合成部署:基于Sherpa-Onnx的MeloTTS多语言模型转换与优化方案
  • 文泉驿微米黑终极安装指南:5MB轻量级中文字体跨平台快速部署
  • 【图像提取】基于数学形态学的数字视网膜图像血管提取 (DRIVE) 数据集分割附Matlab代码
  • 【AI搜索革命性差异指南】:3大核心维度拆解AI搜索与传统搜索的底层逻辑差异
  • 别只用来聊天!解锁BitoAI在VSCode中的5个高效编程场景(含代码规范检查与性能优化)
  • FastAdmin后台开发实战:手把手教你从零新增一个自定义管理页面(ThinkPHP6框架)
  • Simulink封装模块的‘隐藏关卡’:初始化命令与回调函数实战指南(避坑+案例)
  • 深入Windows消息循环:手把手教你用Unity拦截WM_SIZING实现自定义窗口控制
  • 【绿化】Fong投屏 一键手机投屏 多设备兼容超稳定
  • 给STM32CubeIDE新手的第一份保姆级环境搭建指南(含JRE安装、汉化、主题美化)
  • 如何让AI代理操作SCADA和PLC设备获取数据?实在Agent闭锁环实战解析
  • 给Kali 2022.1换张‘脸’:从默认主题到中文界面,一次搞定所有视觉和语言设置
  • COM3D2.MaidFiddler:5分钟掌握COM3D2女仆实时编辑器完整指南
  • 55个功能点解锁炉石传说新体验:HsMod全面优化指南
  • 如何选择工程信息平台?2026年5月推荐口碑好的服务项目人脉难寻痛点 - 品牌推荐
  • CSS View Transitions API 详解
  • 给测试新人的FOTA实战指南:从Tbox到整车,如何高效设计车载固件升级测试用例?
  • Realtek蓝牙鼠标卡顿?别急着换硬件,试试这个被忽略的Windows后台服务优化
  • 5分钟终结VC运行库安装难题:一站式解决方案深度解析
  • Lindy内容创作自动化:从零搭建抗衰减内容引擎的4层架构,含GitHub开源模板
  • Linux系统终极解决方案:Dislocker轻松访问BitLocker加密分区
  • 猫抓扩展终极指南:5步掌握浏览器资源嗅探与安全下载技巧
  • 大模型推理加速实战:VLLM 与 TensorRT-LLM 深度拆解——PagedAttention 如何让吞吐量提升 2.3 倍,量化与部署中的图优化又带来 40% 显存节省?
  • AMBA 总线接口访问明细
  • 手把手教你玩转CST材料库:导入厂家数据、创建自定义吸波材料全攻略
  • 合肥本地招聘为什么首选合肥直聘兔?本土优势+真实数据+落地案例详解 - drfdxr
  • 告别‘蝙蝠翼’困扰:用Ansys Zemax非序列模式精准模拟LED光源(附RSMX文件实战)
  • Agent赋能下药物警戒自动生成的个例报告符合监管要求吗?深度拆解AI Agent在PV领域的合规边界