floating_bottom_nav_bar 1.2.4
floating_bottom_nav_bar: ^1.2.4 copied to clipboard
A customizable floating bottom navigation bar for Flutter with smooth animations, modern UI styling, SVG icon support, and badge indicators.
example/main.dart
import 'package:floating_bottom_nav_bar/app/modules/base/views/base_view.dart';
import 'package:floating_bottom_nav_bar/app/modules/base/views/tab_indicator.dart';
import 'package:floating_frosted_bottom_bar/app/frosted_bottom_bar.dart';
// import 'package:floating_frosted_bottom_bar/app/frosted_bottom_bar.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
// Import your library. If it's local, use a path like:
// import 'package:floating_bottom_nav_bar/lib/floating_bottom_nav_bar.dart';
// For a published package, use:
void main() {
// Ensure GetX is initialized
runApp(GetMaterialApp(
debugShowCheckedModeBanner: false,
title: 'Floating Nav Bar Demo',
theme: ThemeData(
primarySwatch: Colors.purple,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: const MainScreen(),
));
}
// ---------------------------------------------------------------------
// CONTROLLER: Manages the state of the selected tab
// ---------------------------------------------------------------------
class BaseController extends GetxController {
/// Reactive variable to hold the current page index
var currentPage = 0.obs;
/// Method to update the current page
void setPage(int page) {
currentPage.value = page;
}
}
// ---------------------------------------------------------------------
// MAIN SCREEN: The root widget containing the navigation
// ---------------------------------------------------------------------
class MainScreen extends StatefulWidget {
const MainScreen({Key? key}) : super(key: key);
@override
State<MainScreen> createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen>
with TickerProviderStateMixin {
// Instance of the controller
final BaseController controller = Get.put(BaseController());
// TabController for the TabBar
late TabController _tabController;
// List of pages for navigation
final List<Widget> tabPages = const [
HomePage(),
BrowsePage(),
MapsPage(),
FavoritePage(),
MorePage(),
];
@override
void initState() {
super.initState();
// Initialize the TabController
_tabController = TabController(length: 5, vsync: this);
// Listener to sync TabBar animation with GetX state
_tabController.animation?.addListener(() {
final value = _tabController.animation?.value.round();
if (value != null && value != controller.currentPage.value && mounted) {
// This is optional, but can be useful if you want the TabBar's
// swipe gesture to control the page.
// controller.setPage(value);
}
});
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
// Important: Prevent keyboard from resizing the view
resizeToAvoidBottomInset: false,
// The body uses an IndexedStack to preserve the state of each page
body: SafeArea(
bottom: false,
child: Obx(() => IndexedStack(
index: controller.currentPage.value,
children: tabPages,
)),
),
// The bottom navigation bar from your library
bottomNavigationBar: FrostedBottomBar(
opacity: 1.0,
sigmaX: 5,
sigmaY: 5,
borderRadius: BorderRadius.circular(16),
duration: const Duration(milliseconds: 800),
hideOnScroll: true,
// The body is a TabBarView, required by the underlying library
body: (context, scrollController) => TabBarView(
controller: _tabController,
physics: const BouncingScrollPhysics(),
children: tabPages,
),
// The child contains the actual TabBar UI
child: Container(
width: double.infinity,
// The background color of the nav bar
color: const Color(0xFFb22222), // Dark Red
child: TabBar(
controller: _tabController,
// Update the GetX state when a tab is tapped
onTap: (index) {
controller.setPage(index);
// Also animate the TabBar to the correct position
_tabController.animateTo(index);
},
indicatorPadding: const EdgeInsets.fromLTRB(6, 60, 6, 3),
// Use the custom curved indicator from your library
indicator: const CurvedUnderlineTabIndicator(
color: Colors.white,
height: 10,
width: 60,
radius: 30,
),
// Define the tabs with icons and labels
tabs: [
TabsIconWithLabel(
assetPath: "example/assets/icons/icon1.svg",
label: "1",
// Change color based on the active state from the controller
color: controller.currentPage.value == 0
? Colors.white
: Colors.white.withOpacity(0.6),
),
TabsIconWithLabel(
assetPath: "example/assets/icons/icon2.svg",
label: "2",
color: controller.currentPage.value == 1
? Colors.white
: Colors.white.withOpacity(0.6),
),
TabsIconWithLabel(
assetPath: "aexample/assets/icons/icon3.svg",
label: "3",
color: controller.currentPage.value == 2
? Colors.white
: Colors.white.withOpacity(0.6),
),
TabsIconWithLabel(
assetPath: "example/assets/icons/icon4.svg",
label: "4",
color: controller.currentPage.value == 3
? Colors.white
: Colors.white.withOpacity(0.6),
),
TabsIconWithLabel(
assetPath: "example/assets/icons/icon5.svg",
label: "5",
color: controller.currentPage.value == 4
? Colors.white
: Colors.white.withOpacity(0.6),
),
],
),
),
),
);
}
}
// ---------------------------------------------------------------------
// PLACEHOLDER PAGES: Simple widgets to represent each screen
// ---------------------------------------------------------------------
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return pageScaffold('Home Page', Colors.yellow.shade50);
}
}
class BrowsePage extends StatelessWidget {
const BrowsePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return pageScaffold('Browse Page', Colors.green.shade50);
}
}
class MapsPage extends StatelessWidget {
const MapsPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return pageScaffold('Maps Page', Colors.blue.shade50);
}
}
class FavoritePage extends StatelessWidget {
const FavoritePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return pageScaffold('Favorites Page', Colors.red.shade50);
}
}
class MorePage extends StatelessWidget {
const MorePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return pageScaffold('More Page', Colors.purple.shade50);
}
}
// Helper widget to create consistent placeholder pages
Widget pageScaffold(String title, Color color) {
return Container(
color: color,
child: Center(
child: Text(
title,
style: const TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
),
),
);
}