image

22 Feb 2026

9K

35K

Flutter Slide & Fade Animations for Notification Toasts

Notification toasts are ephemeral, non-intrusive messages that provide users with critical feedback without interrupting their workflow. In Flutter, animating these toasts with subtle slide and fade effects significantly enhances the user experience, making them feel more dynamic, intuitive, and less jarring. This article delves into creating professional slide and fade animations for notification toasts in Flutter, leveraging its robust animation framework.

Understanding Flutter Animation Fundamentals

Flutter's animation system is powerful and flexible, built upon a few core concepts that allow for highly customizable and performant animations. Key components for achieving complex animations like slide and fade include:

  • AnimationController: This class manages the animation's state, including its duration, playback direction (forward, reverse), and status (dismissed, forward, reverse, completed). It requires a TickerProvider (usually a State mixing SingleTickerProviderStateMixin or TickerProviderStateMixin) to synchronize with the screen refresh rate.
  • Tween: A Tween (short for "in-between") defines the range of values an animation can interpolate between. For example, a Tween<double> might go from 0.0 to 1.0 for opacity, or a Tween<Offset> could define start and end positions for a slide.
  • Animation: An abstract class that represents an animated value. It's typically produced by a Tween that "animates" a value between its begin and end properties over the duration specified by an AnimationController.
  • Transition Widgets: Flutter provides several pre-built widgets like FadeTransition, SlideTransition, and ScaleTransition. These widgets take an Animation object and apply specific transformations (opacity, position, scale) to their child widget based on the animation's current value.

Crafting the Animated Toast Notification

To create an animated slide and fade notification toast, we'll encapsulate the logic within a custom stateful widget. This widget will manage its own animation controller, define the entry and exit animations, and provide the visual styling for the toast message.

Step 1: The ToastNotification Widget Structure

Our ToastNotification widget will extend StatefulWidget and mix in SingleTickerProviderStateMixin to provide the vsync required by the AnimationController. It will define the message, duration, and a callback for when it's dismissed.


import 'package:flutter/material.dart';

class ToastNotification extends StatefulWidget {
  final String message;
  final Duration duration;
  final VoidCallback? onDismissed;

  const ToastNotification({
    Key? key,
    required this.message,
    this.duration = const Duration(seconds: 3),
    this.onDismissed,
  }) : super(key: key);

  @override
  _ToastNotificationState createState() => _ToastNotificationState();
}

class _ToastNotificationState extends State with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation _slideAnimation;
  late Animation _fadeAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300), // Duration for the animation itself
    );

    // Define slide animation: starts off-screen bottom, slides to natural position
    _slideAnimation = Tween(
      begin: const Offset(0, 1), // Represents 100% of widget height below its position
      end: Offset.zero,          // Represents its natural position
    ).chain(CurveTween(curve: Curves.easeOutCubic)).animate(_controller);

    // Define fade animation: starts invisible, fades to opaque
    _fadeAnimation = Tween(
      begin: 0.0,
      end: 1.0,
    ).chain(CurveTween(curve: Curves.easeIn)).animate(_controller);

    _controller.forward(); // Start the entry animation

    // Set a timer for auto-dismissal
    Future.delayed(widget.duration, () {
      if (mounted) {
        _controller.reverse().then((_) {
          if (mounted) {
            widget.onDismissed?.call();
          }
        });
      }
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SlideTransition(
      position: _slideAnimation,
      child: FadeTransition(
        opacity: _fadeAnimation,
        child: Material(
          color: Colors.transparent, // Important: allows the toast to receive touches without being visible itself
          child: Container(
            margin: const EdgeInsets.all(16.0),
            padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0),
            decoration: BoxDecoration(
              color: Colors.black.withOpacity(0.7),
              borderRadius: BorderRadius.circular(8.0),
              boxShadow: const [
                BoxShadow(
                  color: Colors.black26,
                  blurRadius: 10.0,
                  offset: Offset(0, 5),
                ),
              ],
            ),
            child: Text(
              widget.message,
              style: const TextStyle(color: Colors.white, fontSize: 16.0),
              textAlign: TextAlign.center,
            ),
          ),
        ),
      ),
    );
  }
}

Step 2: Displaying the Toast using OverlayEntry

To display the toast notification independently of the current widget tree and float above all other content, we utilize an OverlayEntry. This mechanism allows us to insert widgets into an Overlay widget, which is typically located at the root of your application.


import 'package:flutter/material.dart';
// Assuming ToastNotification class is defined above

class ToastManager {
  static OverlayEntry? _currentOverlayEntry;

  /// Shows a notification toast at the bottom of the screen.
  /// If another toast is active, it will be dismissed first.
  static void show(BuildContext context, String message, {Duration? duration}) {
    // Dismiss any existing toast to prevent multiple toasts from overlapping
    if (_currentOverlayEntry != null) {
      _currentOverlayEntry!.remove();
      _currentOverlayEntry = null;
    }

    _currentOverlayEntry = OverlayEntry(
      builder: (context) => Positioned(
        bottom: 50, // Controls the distance from the bottom of the screen
        left: 0,
        right: 0,
        child: Align(
          alignment: Alignment.bottomCenter, // Centers the toast horizontally
          child: ToastNotification(
            message: message,
            duration: duration ?? const Duration(seconds: 3),
            onDismissed: () {
              // Remove the overlay entry once the toast animation completes its exit
              _currentOverlayEntry?.remove();
              _currentOverlayEntry = null;
            },
          ),
        ),
      ),
    );

    // Insert the overlay entry into the overlay stack
    Overlay.of(context).insert(_currentOverlayEntry!);
  }
}

Step 3: Triggering the Toast

With the ToastNotification widget and ToastManager in place, you can now easily trigger a toast notification from any part of your application where you have access to a BuildContext.


import 'package:flutter/material.dart';
// Assuming ToastManager and ToastNotification are defined in your project

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Animated Toast Example')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () {
                ToastManager.show(context, "Item added to cart successfully!", duration: const Duration(seconds: 2));
              },
              child: const Text("Show Short Toast"),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                ToastManager.show(context, "An error occurred during data synchronization. Please try again later.", duration: const Duration(seconds: 5));
              },
              child: const Text("Show Longer Toast"),
            ),
          ],
        ),
      ),
    );
  }
}

Best Practices and Customizations

  • Animation Curves: Experiment with different Curve options (e.g., Curves.easeOut, Curves.decelerate, Curves.fastOutSlowIn) to find the perfect feel for your animation. easeOutCubic provides a smooth deceleration for the slide, while easeIn ensures a subtle appearance.
  • Positioning: Adjust the bottom property of the Positioned widget in the OverlayEntry to place the toast at different vertical positions (top, center, bottom) and fine-tune margins for optimal screen real estate and user visibility.
  • Interactivity: Consider adding a GestureDetector to the toast's Container to allow users to dismiss it early by tapping. This would involve calling _controller.reverse() and subsequently removing the OverlayEntry.
  • Theming and Content: Customize the toast's background color, text style, add leading/trailing icons, or even pass in a custom child widget to match your application's design system and convey richer information.
  • Accessibility: For users who might miss visual cues, consider integrating spoken feedback using Flutter's accessibility features (e.g., Semantics or announce through ScaffoldMessenger) in conjunction with the toast.
  • Managing Multiple Toasts: The provided ToastManager removes any active toast before showing a new one. For scenarios requiring multiple toasts to stack or queue up, you would need a more sophisticated manager that handles a list of OverlayEntry objects or uses a dedicated toast queue.

Conclusion

Animating notification toasts with slide and fade effects significantly elevates the user experience in Flutter applications, transforming simple messages into engaging and polished UI elements. By mastering AnimationController, Tween, SlideTransition, FadeTransition, and the OverlayEntry mechanism, developers can create not just toasts, but a wide array of dynamic and professional user interfaces. These techniques are fundamental for building responsive and visually appealing mobile experiences in Flutter.

Related Articles

May 14, 2026

Building a Multi-Event Countdown Timer Widget with Reminders, Notifications, Repeat, and Custom Labels in Flutter

Building a Multi-Event Countdown Timer Widget with Reminders, Notifications, Repeat, and Custom Labels in Flutter Countdown timers are essential in many applic

May 11, 2026

Unleashing Dynamic UIs: Flutter's Animation Prowess

Unleashing Dynamic UIs: Flutter's Animation Prowess for Slide & Scale Effects Flutter's declarative UI framework, combined with its powerful animation capabilit

May 11, 2026

Building a Product Detail Page Widget in Flutter with Related Items, Review Carousel, Promo Badges, and Quick Buy

Building a Product Detail Page Widget in Flutter with Related Items, Review Carousel, Promo Badges, and Quick Buy A well-designed Product Detail Page (PDP) is