liquid_glass_floating_nav 0.1.0
liquid_glass_floating_nav: ^0.1.0 copied to clipboard
A premium floating Liquid Glass bottom navigation bar with smooth drag-to-preview, an organic liquid bubble indicator and light/dark support.
import 'package:flutter/material.dart';
import 'package:liquid_glass_floating_nav/liquid_glass_floating_nav.dart';
void main() => runApp(const ExampleApp());
/// Demonstrates [LiquidGlassBottomNav] over five colourful pages, with light
/// and dark themes that follow the system setting.
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Liquid Glass Floating Nav',
debugShowCheckedModeBanner: false,
// The bar reads its accent from the colour scheme and adapts its glass
// fill to brightness, so light and dark "just work".
theme: ThemeData(
colorSchemeSeed: const Color(0xFF6750A4),
brightness: Brightness.light,
useMaterial3: true,
),
darkTheme: ThemeData(
colorSchemeSeed: const Color(0xFF6750A4),
brightness: Brightness.dark,
useMaterial3: true,
),
home: const HomeShell(),
);
}
}
/// Holds the single source of truth for the selected tab and switches pages
/// with an [IndexedStack] (so each page keeps its state across tab changes).
class HomeShell extends StatefulWidget {
const HomeShell({super.key});
@override
State<HomeShell> createState() => _HomeShellState();
}
class _HomeShellState extends State<HomeShell> {
int _currentIndex = 0;
// Built once and held in State — do NOT recreate on every tab change, or the
// bar's animation controller would be thrown away mid-flight.
static const _items = <LiquidGlassNavItem>[
LiquidGlassNavItem(
icon: Icons.home_outlined,
selectedIcon: Icons.home,
label: 'Home',
),
LiquidGlassNavItem(
icon: Icons.grid_view_outlined,
selectedIcon: Icons.grid_view,
label: 'Shop',
),
LiquidGlassNavItem(
icon: Icons.shopping_cart_outlined,
selectedIcon: Icons.shopping_cart,
label: 'Cart',
semanticLabel: 'Shopping cart',
badgeCount: 3,
),
LiquidGlassNavItem(
icon: Icons.receipt_long_outlined,
selectedIcon: Icons.receipt_long,
label: 'Orders',
),
LiquidGlassNavItem(
icon: Icons.person_outline,
selectedIcon: Icons.person,
label: 'Account',
),
];
static const _pages = <Widget>[
_DemoPage(title: 'Home', icon: Icons.home, color: Color(0xFFEF5350)),
_DemoPage(title: 'Shop', icon: Icons.grid_view, color: Color(0xFF42A5F5)),
_DemoPage(
title: 'Cart', icon: Icons.shopping_cart, color: Color(0xFF66BB6A)),
_DemoPage(
title: 'Orders', icon: Icons.receipt_long, color: Color(0xFFFFA726)),
_DemoPage(title: 'Account', icon: Icons.person, color: Color(0xFFAB47BC)),
];
@override
Widget build(BuildContext context) {
return Scaffold(
// extendBody lets page content flow *under* the floating glass pill so it
// frosts through the blur as it scrolls.
extendBody: true,
body: IndexedStack(index: _currentIndex, children: _pages),
bottomNavigationBar: LiquidGlassBottomNav(
currentIndex: _currentIndex,
items: _items,
onTap: (index) => setState(() => _currentIndex = index),
),
);
}
}
/// A simple colourful, scrollable page so you can see content frosting under
/// the bar. Demo scaffolding only — not part of the package.
class _DemoPage extends StatelessWidget {
const _DemoPage(
{required this.title, required this.icon, required this.color});
final String title;
final IconData icon;
final Color color;
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
SliverAppBar.large(
title: Text(title),
backgroundColor: color,
foregroundColor: Colors.white,
),
SliverPadding(
// Leave room for the floating bar at the bottom of the scroll.
padding: const EdgeInsets.fromLTRB(16, 8, 16, 120),
sliver: SliverList.separated(
itemCount: 20,
separatorBuilder: (_, __) => const SizedBox(height: 12),
itemBuilder: (context, i) => Card(
child: ListTile(
leading: Icon(icon, color: color),
title: Text('$title item ${i + 1}'),
subtitle:
const Text('Scroll to see content frost under the nav'),
),
),
),
),
],
);
}
}