circular_theme_reveal 1.0.2 copy "circular_theme_reveal: ^1.0.2" to clipboard
circular_theme_reveal: ^1.0.2 copied to clipboard

A beautiful Telegram-style circular reveal animation for theme transitions in Flutter. Smooth, performant, and zero dependencies.

Circular Theme Reveal 🎨 #

A beautiful Telegram-style circular reveal animation for theme transitions in Flutter

Telegram-style theme animation demo

pub package style: flutter_lints License: MIT GitHub stars

✨ Smooth β€’ πŸ”„ Bidirectional β€’ ⚑ Performant β€’ 🎯 Zero Dependencies


Features ✨ #

  • πŸ”„ Smooth circular reveal animation - Just like Telegram
  • πŸŒ“ Bidirectional transition - Expands when going dark, contracts when going light
  • 🎯 Center-based animation - Starts from any point (e.g., your theme toggle button)
  • ⚑ High performance - Uses efficient snapshot + blend mode technique
  • 🎨 Customizable - Adjust duration, curves, and more
  • πŸ“¦ Zero dependencies - Only uses Flutter SDK

Installation #

Add this to your pubspec.yaml:

dependencies:
  circular_theme_reveal:

Or install it from the command line:

flutter pub add circular_theme_reveal

Usage #

1. Wrap your MaterialApp #

Wrap your MaterialApp (or the root widget) with CircularThemeRevealOverlay:

import 'package:circular_theme_reveal/circular_theme_reveal.dart';

class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  ThemeMode _themeMode = ThemeMode.light;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Circular Theme Reveal Demo',
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      themeMode: _themeMode,
      themeAnimationDuration: Duration.zero, // Disable default animation
      builder: (context, child) {
        return CircularThemeRevealOverlay(
          child: child ?? SizedBox.shrink(),
        );
      },
      home: HomePage(
        onThemeToggle: () {
          setState(() {
            _themeMode = _themeMode == ThemeMode.light 
                ? ThemeMode.dark 
                : ThemeMode.light;
          });
        },
        isDark: _themeMode == ThemeMode.dark,
      ),
    );
  }
}

2. Trigger the animation #

In your theme toggle button (simplified with helper method):

IconButton(
  icon: Icon(isDark ? Icons.light_mode : Icons.dark_mode),
  onPressed: () async {
    // Get button center position using helper
    final center = CircularThemeRevealOverlay.getCenterFromContext(context);
    
    // Get overlay state
    final overlay = CircularThemeRevealOverlay.of(context);

    if (overlay != null) {
      // Start circular reveal animation
      await overlay.startTransition(
        center: center,
        reverse: isDark, // true when going from dark to light
        onThemeChange: () {
          // Change your theme here
          setState(() {
            isDark = !isDark;
          });
        },
      );
    } else {
      // Fallback if overlay not found
      setState(() {
        isDark = !isDark;
      });
    }
  },
)

Works with Any State Management #

The package is agnostic to your state management solution. Works with:

Provider / Riverpod

onThemeChange: () {
  ref.read(themeProvider.notifier).toggle();
}

Bloc

onThemeChange: () {
  context.read<ThemeBloc>().add(ToggleTheme());
}

GetX

onThemeChange: () {
  Get.find<ThemeController>().toggleTheme();
}

Complete Example #

See the /example folder for a complete working example with:

  • State management
  • Theme persistence
  • Multiple pages
  • Custom theme toggle button

How it works πŸ”§ #

The animation uses a clever technique inspired by Telegram:

  1. Captures a snapshot of the current screen using RepaintBoundary
  2. Overlays the snapshot on top of your app
  3. Changes the theme underneath via your onThemeChange callback
  4. Animates a circular mask using BlendMode.dstOut that reveals the new theme
  5. Fades out gracefully at the end with progressive opacity + glow effect

The animation direction adapts automatically:

  • 🌞 β†’ πŸŒ™ Expands from the button (circle grows, revealing dark theme)
  • πŸŒ™ β†’ 🌞 Contracts back to the button (circle shrinks, revealing light theme)

The contraction uses special techniques to eliminate visual glitches:

  • Fade based on actual radius (not time) for natural dissipation
  • Subtle glow effect in the final 10% for smooth termination
  • easeInExpo curve for cinematic acceleration
  • Precise timing to remove overlay only when fully invisible

Customization #

Current defaults: #

  • Duration: 600ms
  • Expansion curve: Curves.easeInOut
  • Contraction curve: Curves.easeInExpo (more cinematic)
  • Fade threshold: Last 15% of radius
  • Glow effect: Last 10% of radius

Custom themes support: #

The package works with any theme colors because it captures actual rendered pixels:

MaterialApp(
  theme: ThemeData(
    colorScheme: ColorScheme.fromSeed(
      seedColor: Colors.purple,  // βœ… Your custom colors
      brightness: Brightness.light,
    ),
  ),
  darkTheme: ThemeData(
    colorScheme: ColorScheme.fromSeed(
      seedColor: Colors.orange,  // βœ… Your custom dark colors
      brightness: Brightness.dark,
    ),
  ),
  // ... rest of setup
)

Performance Tips #

  • βœ… Uses RepaintBoundary for efficient snapshot capture
  • βœ… Disposes images properly to prevent memory leaks
  • βœ… Uses BlendMode.dstOut for hardware-accelerated masking
  • βœ… Minimal rebuilds during animation

Platform Support #

Platform Support
Android βœ…
iOS βœ…
Web βœ…
macOS βœ…
Windows βœ…
Linux βœ…

Contributing #

Contributions are welcome! Please feel free to submit a Pull Request.

License #

MIT License - see LICENSE file for details

Credits #

Inspired by Telegram's beautiful theme transition animation.

Author #

Created with ❀️ by marcospereira

2
likes
150
points
171
downloads

Publisher

unverified uploader

Weekly Downloads

A beautiful Telegram-style circular reveal animation for theme transitions in Flutter. Smooth, performant, and zero dependencies.

Repository (GitHub)
View/report issues

Topics

#animation #theme #telegram #circular-reveal #dark-mode

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on circular_theme_reveal