extended_bottom_navigation_bar 1.0.4 copy "extended_bottom_navigation_bar: ^1.0.4" to clipboard
extended_bottom_navigation_bar: ^1.0.4 copied to clipboard

A clean, highly customizable and expandable bottom navigation bar with a central FAB slot and staggered animation grid.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:extended_bottom_navigation_bar/extended_bottom_navigation_bar.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Extended Bottom Nav Bar Demo',
      debugShowCheckedModeBanner: false,
      themeMode: ThemeMode.system,
      theme: ThemeData(
        brightness: Brightness.light,
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF6200EE),
          brightness: Brightness.light,
        ),
      ),
      darkTheme: ThemeData(
        brightness: Brightness.dark,
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFFBB86FC),
          brightness: Brightness.dark,
        ),
      ),
      home: const DemoPage(),
    );
  }
}

class DemoPage extends StatefulWidget {
  const DemoPage({super.key});

  @override
  State<DemoPage> createState() => _DemoPageState();
}

class _DemoPageState extends State<DemoPage> {
  int _currentIndex = 0;
  bool _isNavExpanded = false;
  bool _showNotchAndFab = true;

  // Track the name of the last tapped secondary item
  String _lastSecondaryTapped = 'None';

  // Navigation handlers
  void _onTabSelect(int index) {
    setState(() {
      _currentIndex = index;
    });
  }

  void _onSecondaryItemTap(String label) {
    setState(() {
      _lastSecondaryTapped = label;
    });
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text('Selected secondary action: $label'),
        duration: const Duration(seconds: 2),
        behavior: SnackBarBehavior.floating,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final isDark = theme.brightness == Brightness.dark;

    // Define Left and Right Primary Items
    final leftItems = [
      PrimaryNavBarItem(
        icon: Icons.home_outlined,
        activeIcon: Icons.home,
        label: 'Home',
        isActive: _currentIndex == 0,
        onTap: () => _onTabSelect(0),
      ),
      PrimaryNavBarItem(
        icon: Icons.analytics_outlined,
        activeIcon: Icons.analytics,
        label: 'Analytics',
        isActive: _currentIndex == 1,
        onTap: () => _onTabSelect(1),
      ),
    ];

    final rightItems = [
      PrimaryNavBarItem(
        icon: Icons.notifications_none_outlined,
        activeIcon: Icons.notifications,
        label: 'Alerts',
        isActive: _currentIndex == 2,
        onTap: () => _onTabSelect(2),
      ),
      // Note: If secondaryItems is not empty, you can only have 1 rightItem,
      // as the 2nd slot is taken up by the grid "More" toggle tab.
      if (!_showNotchAndFab)
        PrimaryNavBarItem(
          icon: Icons.settings_outlined,
          activeIcon: Icons.settings,
          label: 'Settings',
          isActive: _currentIndex == 3,
          onTap: () => _onTabSelect(3),
        ),
    ];

    // Define Secondary (Expanded Grid) Items
    final secondaryItems = [
      SecondaryNavBarItem(
        icon: Icons.account_balance_wallet_outlined,
        activeIcon: Icons.account_balance_wallet,
        label: 'Wallet',
        onTap: () => _onSecondaryItemTap('Wallet'),
      ),
      SecondaryNavBarItem(
        icon: Icons.receipt_long_outlined,
        activeIcon: Icons.receipt_long,
        label: 'Invoices',
        onTap: () => _onSecondaryItemTap('Invoices'),
      ),
      SecondaryNavBarItem(
        icon: Icons.people_outline,
        activeIcon: Icons.people,
        label: 'Contacts',
        onTap: () => _onSecondaryItemTap('Contacts'),
      ),
      SecondaryNavBarItem(
        icon: Icons.calculate_outlined,
        activeIcon: Icons.calculate,
        label: 'Calculator',
        onTap: () => _onSecondaryItemTap('Calculator'),
      ),
      SecondaryNavBarItem(
        icon: Icons.category_outlined,
        activeIcon: Icons.category,
        label: 'Categories',
        onTap: () => _onSecondaryItemTap('Categories'),
      ),
      SecondaryNavBarItem(
        icon: Icons.help_outline,
        activeIcon: Icons.help,
        label: 'Help',
        onTap: () => _onSecondaryItemTap('Help'),
      ),
    ];

    // Page titles to render in body
    final pages = [
      'Dashboard & Home Overview',
      'Detailed Analytics & Reports',
      'Recent Notifications & Alerts',
      'System Settings & Config',
    ];

    // Center FAB Widget
    final customFab = GestureDetector(
      onTap: () {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text('Central FAB Tapped!'),
            behavior: SnackBarBehavior.floating,
          ),
        );
      },
      child: Container(
        width: 60,
        height: 60,
        decoration: BoxDecoration(
          shape: BoxShape.circle,
          gradient: const LinearGradient(
            colors: [Colors.purpleAccent, Colors.blueAccent],
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
          ),
          boxShadow: [
            BoxShadow(
              color: Colors.blueAccent.withValues(alpha: 0.4),
              blurRadius: 12,
              offset: const Offset(0, 4),
            ),
          ],
        ),
        child: const Icon(
          Icons.add,
          color: Colors.white,
          size: 30,
        ),
      ),
    );

    return Scaffold(
      body: Stack(
        children: [
          // Background Color / Content
          Positioned.fill(
            child: Container(
              color: isDark ? const Color(0xFF121212) : const Color(0xFFF6F6F9),
            ),
          ),

          // Main Scrollable Content
          SafeArea(
            child: CustomScrollView(
              physics: const BouncingScrollPhysics(),
              slivers: [
                SliverAppBar(
                  expandedHeight: 120,
                  floating: false,
                  pinned: true,
                  flexibleSpace: FlexibleSpaceBar(
                    title: Text(
                      'Extended Bottom Nav Bar',
                      style: TextStyle(
                        color: isDark ? Colors.white : Colors.black,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    centerTitle: false,
                  ),
                ),
                SliverToBoxAdapter(
                  child: Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        // Card with Info
                        Card(
                          elevation: 2,
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(16),
                          ),
                          child: Padding(
                            padding: const EdgeInsets.all(16.0),
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                Text(
                                  'Current Tab: ${pages[_currentIndex.clamp(0, pages.length - 1)]}',
                                  style: theme.textTheme.titleMedium?.copyWith(
                                    fontWeight: FontWeight.bold,
                                  ),
                                ),
                                const SizedBox(height: 8),
                                Text(
                                  'Last Tapped Grid Item: $_lastSecondaryTapped',
                                  style: theme.textTheme.bodyMedium?.copyWith(
                                    color: theme.colorScheme.secondary,
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ),
                        const SizedBox(height: 24),

                        Text(
                          'Configuration Controls',
                          style: theme.textTheme.titleLarge?.copyWith(
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                        const SizedBox(height: 12),

                        // Switch to toggle FAB / Notch
                        SwitchListTile(
                          value: _showNotchAndFab,
                          title: const Text('Show Notch & Central FAB'),
                          subtitle: const Text(
                              'Toggle the center floating action button & notch clipper.'),
                          onChanged: (val) {
                            setState(() {
                              _showNotchAndFab = val;
                              // Ensure current index is in range if we shift layout
                              if (!val && _currentIndex > 3) {
                                _currentIndex = 0;
                              }
                            });
                          },
                        ),

                        const Divider(),
                        const SizedBox(height: 12),

                        Text(
                          'About this package',
                          style: theme.textTheme.titleMedium?.copyWith(
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                        const SizedBox(height: 8),
                        const Text(
                          'This package delivers an expandable footer navigation bar, supporting left/right tabs, a center FAB layout, and a hidden grid for secondary options. It includes staggered slide and fade animations when expanded.',
                        ),
                        const SizedBox(height: 120), // Padding to allow scrolling past bottom bar
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),

          // Backdrop Overlay to dim screen when expanded
          if (_isNavExpanded)
            Positioned.fill(
              child: GestureDetector(
                onTap: () {
                  // Collapse via a dynamic action or tapping the overlay
                  // Note: The ExpandableBottomNav handles collapses on tab selections,
                  // but we can force collapse by rebuilding/tapping the backdrop,
                  // or letting it naturally toggle on the navigation bar button tap.
                },
                child: AnimatedContainer(
                  duration: const Duration(milliseconds: 250),
                  color: Colors.black.withValues(alpha: 0.4),
                ),
              ),
            ),
        ],
      ),
      bottomNavigationBar: ExpandableBottomNav(
        leftItems: leftItems,
        rightItems: rightItems,
        secondaryItems: _showNotchAndFab ? secondaryItems : const [],
        fab: _showNotchAndFab ? customFab : null,
        notchRadius: 32,
        curve: Curves.easeInCubic,
        
        fabSize: 40,
        onExpandChanged: (expanded) {
          setState(() {
            _isNavExpanded = expanded;
          });
        },
        moreLabel: 'Explore',
        closeLabel: 'Close',
        activeColor: Colors.deepPurple,
        inactiveColor: isDark ? Colors.grey[400] : Colors.grey[600],
        backgroundColor: isDark ? const Color(0xFF1E1E2C) : Colors.white,
      ),
    );
  }
}
2
likes
160
points
52
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A clean, highly customizable and expandable bottom navigation bar with a central FAB slot and staggered animation grid.

Homepage
Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on extended_bottom_navigation_bar