flutterflutter-animationflutter-routes

How to apply reverse animation on Navigator.pop() using flutter_animate package?


I'm applying a fade animation to my full-screen overlay widget using flutter_animate.

Animating "opening" the overlay is as simple as adding a single line of code like Animate(effects: const [FadeEffect()], child: const AddOverlay()),)

However, I cannot figure out how to reverse the fade effect when closing the overlay using Navigator.of(context).pop(context);

Below is a minimum reproducible code, with a default boilerplate flutter project.

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Animated Transition',
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.of(context).push(
            PageRouteBuilder(
              opaque: false,
              pageBuilder: (BuildContext context, _, __) => Animate(
                  effects: const [FadeEffect()],
                  child:
                      const AddOverlay()), // Using flutter_animate package to add animation to opening the overlay widget
            ),
          );
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

class AddOverlay extends StatelessWidget {
  const AddOverlay({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black.withOpacity(0.85),
      body: BackdropFilter(
        filter: ImageFilter.blur(
          sigmaX: 5.0,
          sigmaY: 5.0,
        ),
        child: Center(
            child: ElevatedButton(
                onPressed: () {
                  Navigator.of(context).pop(
                      context); // Closing the overlay should also have a fade animation effect.
                },
                child: const Text("Close"))),
      ),
    );
  }
}

Solution

  • I don't see why we need to use flutter_animate for this case. You can achieve the desired effect by using the built-in FadeTransition widget combined with the pageTransitionBuilder, which allows you to customize the animation during the page push or pop transition. When pushing, the animation value will go from 0 to 1.0, and it will reverse when the route is popping.

    The routing part where customise the transition :

      void _navigateToAddOverlay(BuildContext context) {
        Navigator.of(context).push(
          PageRouteBuilder(
            opaque: false,
            reverseTransitionDuration: const Duration(seconds: 5),
            transitionsBuilder: (context, animation, secondaryAnimation, child) {
              return FadeTransition(opacity: animation, child: child);
            },
            pageBuilder: (_, __, ___) => const AddOverlay(),
          ),
        );
      }
    

    here is your full updated code: https://zapp.run/edit/flutter-zk3e0614k3f0?entry=lib/main.dart&file=lib/main.dart