Flutter如何实现Material Design父子过渡效果?是否可使用SizeTransition?
Flutter Material Design 父子层级过渡实现方案
完全可以通过 PageRouteBuilder 配合 Animated 系列组件实现该效果,具体实现逻辑如下:
核心原理
Material Design 规范中的父子层级过渡本质是「共享元素位移+新页面淡入上移」的组合动画,Flutter 官方提供的 Hero 组件天生支持跨页面共享元素动画,搭配 PageRouteBuilder 自定义页面过渡效果即可同时实现正向跳转、反向返回的双向动画。
实现步骤
- 给 SliverList 中需要跳转的子组件包裹
Hero组件,给每个列表项分配唯一的tag,详情页中对应的共享元素也需要使用相同的tag,即可自动实现跨页面的共享元素过渡效果。 - 自定义
PageRouteBuilder,配置双向过渡的参数:- 正向跳转时,新页面从下方20%的位置向上滑动到屏幕顶部,同时透明度从0渐变到1,动画时长控制在300ms符合Material规范
- 反向返回时,动画参数反向执行,新页面向下滑动同时透明度降到0,原有页面恢复显示
- 如果有更定制化的动画需求,可以继承
AnimatedWidget自定义动画组件,绑定PageRouteBuilder的animation对象控制属性插值即可。
示例代码
// 自定义父子层级过渡路由 PageRoute buildHierarchicalTransitionRoute(Widget targetPage) { return PageRouteBuilder( pageBuilder: (context, animation, secondaryAnimation) => targetPage, transitionsBuilder: (context, animation, secondaryAnimation, child) { // 位移动画:从下往上移动 final slideTween = Tween<Offset>( begin: const Offset(0, 0.2), end: Offset.zero, ).chain(CurveTween(curve: Curves.easeInOut)); // 透明度动画 final opacityTween = Tween<double>( begin: 0.0, end: 1.0, ).chain(CurveTween(curve: Curves.easeInOut)); return FadeTransition( opacity: animation.drive(opacityTween), child: SlideTransition( position: animation.drive(slideTween), child: child, ), ); }, transitionDuration: const Duration(milliseconds: 300), reverseTransitionDuration: const Duration(milliseconds: 300), ); } // 列表页使用示例 SliverList( delegate: SliverChildBuilderDelegate( (context, index) => GestureDetector( onTap: () => Navigator.push( context, buildHierarchicalTransitionRoute(DetailPage(itemId: index)), ), // 共享元素绑定唯一tag child: Hero( tag: 'list_item_$index', child: const ListItemCard(), ), ), childCount: 30, ), ) // 详情页对应位置同样包裹同tag的Hero组件即可
如果不需要共享元素效果,直接去掉Hero包裹即可,仅保留PageRouteBuilder的过渡效果也完全符合父子层级过渡的规范要求。
内容的提问来源于stack exchange,提问作者user6097845
相关产品推荐
相关产品推荐

