slide_glass_nav_bar 0.1.0 copy "slide_glass_nav_bar: ^0.1.0" to clipboard
slide_glass_nav_bar: ^0.1.0 copied to clipboard

A floating liquid-glass bottom nav bar with press-and-hold + slide-to-select gestures, an elastic bounce on commit, and full RTL support.

example/lib/main.dart

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

void main() => runApp(const ExampleApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'slide_glass_nav_bar example',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(useMaterial3: true, brightness: Brightness.light),
      home: const _HomePage(),
    );
  }
}

class _HomePage extends StatefulWidget {
  const _HomePage();

  @override
  State<_HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<_HomePage> {
  int _index = 0;
  bool _rtl = false;
  bool _customColors = false;

  static const _pages = [
    _ColorPage(label: 'Home', color: Color(0xFFFFEFD5)),
    _ColorPage(label: 'Search', color: Color(0xFFD0F0FF)),
    _ColorPage(label: 'Library', color: Color(0xFFE6F4EA)),
    _ColorPage(label: 'Profile', color: Color(0xFFFFE2EC)),
  ];

  static const _items = [
    SlideGlassNavItem(label: 'Home', iconBuilder: _iconHome),
    SlideGlassNavItem(label: 'Search', iconBuilder: _iconSearch),
    SlideGlassNavItem(label: 'Library', iconBuilder: _iconLibrary),
    SlideGlassNavItem(label: 'Profile', iconBuilder: _iconProfile),
  ];

  static Widget _iconHome(BuildContext context, Color color, double size) =>
      Icon(Icons.home_rounded, color: color, size: size);
  static Widget _iconSearch(BuildContext context, Color color, double size) =>
      Icon(Icons.search_rounded, color: color, size: size);
  static Widget _iconLibrary(BuildContext context, Color color, double size) =>
      Icon(Icons.collections_bookmark_rounded, color: color, size: size);
  static Widget _iconProfile(BuildContext context, Color color, double size) =>
      Icon(Icons.person_rounded, color: color, size: size);

  @override
  Widget build(BuildContext context) {
    final style = _customColors
        ? const SlideGlassNavBarStyle(
            selectedForegroundColor: Color(0xFF6750A4),
            selectedPillColor: Color(0x33B69DF8),
            selectedPillBorderColor: Color(0x66FFFFFF),
          )
        : const SlideGlassNavBarStyle();

    return Directionality(
      textDirection: _rtl ? TextDirection.rtl : TextDirection.ltr,
      child: Scaffold(
        body: Stack(
          children: [
            IndexedStack(index: _index, children: _pages),
            Positioned(
              top: MediaQuery.of(context).padding.top + 16,
              left: 16,
              right: 16,
              child: _Controls(
                rtl: _rtl,
                customColors: _customColors,
                onRtlChanged: (v) => setState(() => _rtl = v),
                onColorsChanged: (v) => setState(() => _customColors = v),
              ),
            ),
            Positioned(
              left: 0,
              right: 0,
              bottom: 0,
              child: SlideGlassNavBar(
                currentIndex: _index,
                onChanged: (i) => setState(() => _index = i),
                items: _items,
                style: style,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class _Controls extends StatelessWidget {
  final bool rtl;
  final bool customColors;
  final ValueChanged<bool> onRtlChanged;
  final ValueChanged<bool> onColorsChanged;

  const _Controls({
    required this.rtl,
    required this.customColors,
    required this.onRtlChanged,
    required this.onColorsChanged,
  });

  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 0,
      color: const Color(0xDCFFFFFF),
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(20),
        side: const BorderSide(color: Color(0x22000000)),
      ),
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            SwitchListTile(
              title: const Text('RTL layout'),
              value: rtl,
              onChanged: onRtlChanged,
              dense: true,
              contentPadding: EdgeInsets.zero,
            ),
            SwitchListTile(
              title: const Text('Custom selected color'),
              value: customColors,
              onChanged: onColorsChanged,
              dense: true,
              contentPadding: EdgeInsets.zero,
            ),
          ],
        ),
      ),
    );
  }
}

class _ColorPage extends StatelessWidget {
  final String label;
  final Color color;
  const _ColorPage({required this.label, required this.color});

  @override
  Widget build(BuildContext context) {
    return Container(
      color: color,
      child: ListView.builder(
        padding: const EdgeInsets.fromLTRB(20, 160, 20, 160),
        itemCount: 30,
        itemBuilder: (context, i) {
          return Container(
            margin: const EdgeInsets.only(bottom: 12),
            padding: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: const Color(0xB4FFFFFF),
              borderRadius: BorderRadius.circular(16),
            ),
            child: Text(
              '$label item ${i + 1}',
              style: const TextStyle(fontSize: 16),
            ),
          );
        },
      ),
    );
  }
}
1
likes
160
points
6
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A floating liquid-glass bottom nav bar with press-and-hold + slide-to-select gestures, an elastic bounce on commit, and full RTL support.

Repository (GitHub)
View/report issues

Topics

#navigation #bottom-navigation #liquid-glass #rtl #glass

License

MIT (license)

Dependencies

flutter

More

Packages that depend on slide_glass_nav_bar