Flutter:禁用页面返回且保留Hero组件动画?Navigator方法致动画失效
Great question! The issue with pushAndRemoveUntil and pushReplacement is that they modify the navigation stack during the transition, which breaks Hero animations—Hero relies on both the source and destination routes being present in the stack while the animation runs.
Here's a clean solution that preserves the Hero transition while preventing users from navigating back to the Splash screen:
Step 1: Use a regular Navigator.push for the initial transition
Instead of replacing or removing routes upfront, keep the Splash route in the stack temporarily so the Hero animation can complete normally:
// In your SplashScreen widget Navigator.push( context, MaterialPageRoute(builder: (context) => LoginPage()), );
Step 2: Block back navigation in the LoginPage
Use Flutter's PopScope (recommended for Flutter 3.12+) or WillPopScope (for older versions) to intercept back button presses, preventing users from returning to the Splash screen.
Using PopScope (Flutter 3.12+)
class LoginPage extends StatelessWidget { @override Widget build(BuildContext context) { return PopScope( // Disable default back navigation canPop: false, onPopInvoked: (didPop) { // Optional: Add custom logic here (e.g., show a confirmation dialog) // If you don't need any feedback, leave this empty }, child: Scaffold( body: Center( // Your Hero widget matching the one in SplashScreen child: Hero( tag: 'splash-logo', child: Image.asset('assets/logo.png'), ), ), ), ); } }
Using WillPopScope (pre-Flutter 3.12)
class LoginPage extends StatelessWidget { @override Widget build(BuildContext context) { return WillPopScope( onWillPop: () async { // Return false to block the back navigation return false; }, child: Scaffold( // Your LoginPage UI including the Hero widget ), ); } }
Step 3: Clean up the stack after login (optional but recommended)
Once the user successfully logs in, you can safely clear the Splash and Login routes from the stack using pushAndRemoveUntil—this won't affect the original Hero animation since it's already completed:
// In LoginPage, after successful authentication Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (context) => HomePage()), (route) => false, // Removes all previous routes );
This approach keeps the Hero animation intact because the Splash route stays in the stack during the transition, and we only block navigation back rather than removing the route immediately. It's the best of both worlds!
内容的提问来源于stack exchange,提问作者Alejandro Gabriel




