anydrawer 2.0.0 copy "anydrawer: ^2.0.0" to clipboard
anydrawer: ^2.0.0 copied to clipboard

A powerful Flutter drawer that slides from any edge — left, right, top, or bottom. No Scaffold required. Supports backdrop blur, drag gestures, return values, multiple drawers, swipe-from-edge, and de [...]

AnyDrawer - Drawers from any edge, no Scaffold needed

AnyDrawer

Beautiful drawers from any edge. No Scaffold needed.

Pub Version Pub Likes Pub Points Popularity License

Very Good Analysis GitHub Issues

Android iOS Web macOS Windows Linux


Why AnyDrawer? #

Flutter's built-in Drawer widget is tied to Scaffold, limited to left/right, and gives you little control. AnyDrawer removes all those constraints.

Feature Flutter Drawer AnyDrawer
No Scaffold required
Slide from any edge (L/R/T/B) ❌ Left/Right only ✅ All four sides
Backdrop blur (frosted glass)
Return results (Future)
Multiple drawers at once
Drag to dismiss with callbacks
Swipe-from-edge gesture
Declarative widget API
Elevation and shadow
Custom barrier builder
Programmatic open/close/state
Width constraints (min/max)
Custom animation curve
Works with dialogs on top
Accessibility (semantics) Partial

✨ Features at a Glance #

  • 🎯 No Scaffold needed — show a drawer from literally anywhere
  • ↔️ All four sides — slide in from left, right, top, or bottom
  • 🌫️ Backdrop blur — frosted glass effect behind the drawer
  • 🔄 Result returnshowDrawer<T>() returns Future<T?> like showDialog
  • 📚 Multiple drawers — open several drawers simultaneously
  • 🖱️ Drag to close — optional drag gesture support with callbacks
  • 🎮 Programmatic controlAnyDrawerController to open/close from code
  • 🧩 Declarative APIAnyDrawer widget for embedding in the widget tree
  • 👆 Swipe-from-edgeAnyDrawerRegion detects edge swipes to open
  • Elevation & shadow — Material shadow on the drawer edge
  • 🎨 Custom barrier — provide your own barrier widget
  • ⌨️ Close on Escape / Back — keyboard and Android back button
  • 📐 Width constraintsmaxWidth and minWidth for responsive layouts
  • Accessibility — built-in semantics label support

📸 Preview #

Web / Tablet — grid layout with settings drawer

Web example with settings drawer

Mobile — dialog over drawer · return results · drawer settings

Dialog over drawer    Return result from drawer    Drawer settings panel


Installation #

dependencies:
  anydrawer: ^2.0.0
flutter pub get

Quick Start #

Imperative API #

import 'package:anydrawer/anydrawer.dart';

showDrawer(
  context,
  builder: (context) {
    return const Center(
      child: Text('Hello from the drawer!'),
    );
  },
);

Declarative API #

final controller = AnyDrawerController();

// In your widget tree:
AnyDrawer(
  controller: controller,
  builder: (context) => const MyDrawerContent(),
  config: const DrawerConfig(side: DrawerSide.left),
);

// Open/close from anywhere:
controller.open();
controller.close();

Swipe-from-Edge #

AnyDrawerRegion(
  side: DrawerSide.left,
  builder: (context) => const NavigationMenu(),
  config: const DrawerConfig(side: DrawerSide.left, dragEnabled: true),
  child: const MyPageContent(),
)

Configuration #

Pass a DrawerConfig to customize behavior and appearance:

showDrawer(
  context,
  builder: (context) => const MyDrawerContent(),
  config: const DrawerConfig(
    side: DrawerSide.left,
    widthPercentage: 0.4,
    borderRadius: 24,
    backdropOpacity: 0.5,
    backdropBlur: 5.0,
    closeOnClickOutside: true,
    closeOnEscapeKey: true,
    closeOnResume: true,       // Android only
    closeOnBackButton: true,   // Requires a route navigator
    dragEnabled: true,
    curve: Curves.easeOutCubic,
    maxWidth: 400,
    elevation: 8,
    semanticsLabel: 'Navigation drawer',
  ),
  onOpen: () => print('Drawer opened'),
  onClose: () => print('Drawer closed'),
  onDragUpdate: (details) => print('Dragging: ${details.primaryDelta}'),
  onDragEnd: (details) => print('Drag ended'),
);

DrawerConfig Properties #

Property Type Default Description
side DrawerSide right Side the drawer slides in from
widthPercentage double? auto Size fraction of primary axis (0.1 – 0.99)
borderRadius double 20 Corner radius of the drawer edge
backdropOpacity double 0.4 Opacity of the dark backdrop (0 – 1)
backdropBlur double 0.0 Blur sigma for frosted glass backdrop
animationDuration Duration 300ms Slide animation duration
curve Curve Curves.easeInOut Animation curve for the slide transition
closeOnClickOutside bool true Close when tapping the backdrop
closeOnEscapeKey bool true Close on Escape key press
closeOnResume bool false Close when app resumes (Android only)
closeOnBackButton bool false Close on Android back button
dragEnabled bool false Allow drag to dismiss
maxDragExtent double 300 Maximum drag distance
maxWidth double? Maximum pixel size constraint
minWidth double? Minimum pixel size constraint
elevation double 0.0 Material shadow elevation
shadowColor Color? Shadow color when elevation is set
barrierBuilder BarrierBuilder? Custom barrier widget builder
semanticsLabel String? Accessibility label for screen readers
resizable bool false Enable animated runtime size changes

Returning Results #

showDrawer returns a Future<T?>, just like showDialog:

final result = await showDrawer<String>(
  context,
  builder: (context) {
    return Center(
      child: ElevatedButton(
        onPressed: () => Navigator.of(context).pop('selected!'),
        child: const Text('Select'),
      ),
    );
  },
);
print(result); // 'selected!'

Programmatic Control #

Use AnyDrawerController to open and close the drawer from code:

final controller = AnyDrawerController();

showDrawer(
  context,
  builder: (context) => MyDrawerContent(),
  controller: controller,
  onClose: () {
    // Safe to dispose here — onClose is deferred automatically
    controller.dispose();
  },
);

// Check state
print(controller.isOpen); // true

// Close the drawer later
controller.close();

Top & Bottom Drawers #

Show drawers from any edge of the screen:

// Bottom panel (like a custom bottom sheet)
showDrawer(
  context,
  builder: (context) => const DetailsPanel(),
  config: const DrawerConfig(
    side: DrawerSide.bottom,
    widthPercentage: 0.4,  // 40% of screen height
    borderRadius: 20,
  ),
);

// Top notification bar
showDrawer(
  context,
  builder: (context) => const NotificationBar(),
  config: const DrawerConfig(
    side: DrawerSide.top,
    widthPercentage: 0.15,
    backdropOpacity: 0.2,
  ),
);

Backdrop Blur #

Add a frosted glass effect behind the drawer:

showDrawer(
  context,
  builder: (context) => const MyDrawerContent(),
  config: const DrawerConfig(
    backdropBlur: 8.0,
    backdropOpacity: 0.2,
  ),
);

Custom Barrier #

Provide a completely custom barrier widget:

showDrawer(
  context,
  builder: (context) => const MyDrawerContent(),
  config: DrawerConfig(
    barrierBuilder: (context, animation) {
      return GestureDetector(
        onTap: () => Navigator.of(context).pop(),
        child: AnimatedBuilder(
          animation: animation,
          builder: (context, child) => Container(
            color: Colors.purple.withValues(alpha: 0.3 * animation.value),
          ),
        ),
      );
    },
  ),
);

Showing Dialogs Inside the Drawer #

Dialogs, bottom sheets, and menus work seamlessly from inside the drawer:

showDrawer(
  context,
  builder: (context) {
    return Center(
      child: ElevatedButton(
        onPressed: () {
          showDialog(
            context: context,
            builder: (context) => AlertDialog(
              title: Text('Hello!'),
              content: Text('This dialog appears above the drawer.'),
            ),
          );
        },
        child: Text('Show Dialog'),
      ),
    );
  },
);

Multiple Drawers #

You can open multiple drawers simultaneously — for example, a left navigation drawer and a right details panel:

// Open left drawer
showDrawer(
  context,
  builder: (context) => const NavigationMenu(),
  config: const DrawerConfig(
    side: DrawerSide.left,
    widthPercentage: 0.35,
    backdropOpacity: 0.1,
    closeOnClickOutside: false,
  ),
);

// Open right drawer on top
showDrawer(
  context,
  builder: (context) => const DetailsPanel(),
  config: const DrawerConfig(
    side: DrawerSide.right,
    widthPercentage: 0.35,
  ),
);

You can also open nested drawers from inside an existing drawer.

Deep Linking #

Open a drawer in response to a deep link or push notification:

MaterialApp(
  onGenerateRoute: (settings) {
    if (settings.name == '/settings') {
      return MaterialPageRoute(
        builder: (context) {
          WidgetsBinding.instance.addPostFrameCallback((_) {
            showDrawer(
              context,
              builder: (ctx) => const SettingsDrawer(),
              config: const DrawerConfig(side: DrawerSide.right),
            );
          });
          return const HomePage();
        },
      );
    }
    return null;
  },
);

Migration from 1.x #

Breaking changes in 2.0.0 #

  1. showDrawer returns Future<T?> — previously returned void. Callers that ignore the return value need no changes.
  2. DrawerSide has new valuestop and bottom were added. If you have exhaustive switch statements on DrawerSide, add cases for the new values.
  3. Assertion removed — previously, either closeOnClickOutside or closeOnEscapeKey had to be true. Now both can be false.

Contributing #

Pull requests are welcome! For major changes, please open an issue first to discuss what you would like to change.

Support #

If you find this package useful, consider:

License #

This project is licensed under the MIT License.

34
likes
150
points
473
downloads
screenshot

Publisher

verified publishernbhatt.com.np

Weekly Downloads

A powerful Flutter drawer that slides from any edge — left, right, top, or bottom. No Scaffold required. Supports backdrop blur, drag gestures, return values, multiple drawers, swipe-from-edge, and declarative API.

Repository (GitHub)
View/report issues

Topics

#drawer #navigation #panel #overlay #widget

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on anydrawer