如何使用Navigator 2.0实现页面替换时的过渡动画效果
问题根因
Flutter Navigator 2.0 的内置过渡动画默认仅在 pages 数组长度发生变化(新增/删除页面元素)时触发。你每次替换 pages 数组的唯一元素时,数组长度没有变化,因此不会触发动画逻辑。
可行解决方案
方案1:自定义带过渡的Page,无需维护多页面元素
继承 Page 类实现强制过渡动画的自定义页面,直接替换原有 MaterialPage 即可,不需要修改 pages 数组长度,也不需要维护额外的页面栈。
import 'package:flutter/material.dart'; class AnimatedReplacePage extends Page { final Widget child; const AnimatedReplacePage({ required this.child, LocalKey? key, }) : super(key: key); @override Route createRoute(BuildContext context) { return PageRouteBuilder( settings: this, transitionDuration: const Duration(milliseconds: 400), reverseTransitionDuration: const Duration(milliseconds: 400), pageBuilder: (context, animation, secondaryAnimation) => child, // 可自行替换为你需要的过渡效果,以下是iOS风格右滑进入效果 transitionsBuilder: (context, animation, secondaryAnimation, child) { final tween = Tween(begin: const Offset(1.0, 0.0), end: Offset.zero) .chain(CurveTween(curve: Curves.easeOut)); return SlideTransition( position: animation.drive(tween), child: child, ); }, ); } }
替换后的Navigator配置:
final page = ... return Scaffold( body: Navigator( onPopPage: (Route<dynamic> route, dynamic result) { return route.didPop(result); }, pages: [ // 每次页面更新时传入唯一key,用于识别页面变化 AnimatedReplacePage( key: ValueKey(page.runtimeType), child: page, ), ], ), ... );
方案2:极简适配,临时触发长度变化
如果不想自定义Page,只需要在页面切换时临时保留旧页面元素,等动画播放完成后自动移除即可,仅需要维护一个当前页面变量,不需要手动管理完整页面栈。
// 状态变量定义 Widget currentPage = const HomePage(); Widget? _tempPreviousPage; // 页面切换方法 void updatePage(Widget newPage) { _tempPreviousPage = currentPage; currentPage = newPage; setState(() {}); // 动画结束后清空临时旧页面 Future.delayed(const Duration(milliseconds: 400), () { _tempPreviousPage = null; setState(() {}); }); } // Navigator配置 body: Navigator( onPopPage: (route, result) => route.didPop(result), pages: [ if (_tempPreviousPage != null) MaterialPage(child: _tempPreviousPage!), MaterialPage(child: currentPage), ], )
该方案利用pages数组长度从1变为2触发系统自带的页面过渡动画,动画结束后自动恢复为1个页面元素,无需额外维护栈逻辑。
内容的提问来源于stack exchange,提问作者IL_Agent
相关产品推荐
相关产品推荐

