Aidra Driver 1.3.5+68
Aidra Driver - Your path to green energy
Loading...
Searching...
No Matches
nav_bar.dart
Go to the documentation of this file.
1import 'package:flutter/material.dart';
2import 'package:flutter_screenutil/flutter_screenutil.dart';
3import 'package:go_router/go_router.dart';
4
5import '../theme/color_palette.dart';
6
7class NavBar extends StatefulWidget {
8 final StatefulNavigationShell navigationShell;
9 final Widget? body;
10 const NavBar(this.navigationShell, {super.key, this.body});
11
12 @override
13 State<NavBar> createState() => _NavBarState();
14}
15
16class _NavBarState extends State<NavBar> with TickerProviderStateMixin {
18 late List<AnimationController> _animationControllers;
19 late List<Animation<double>> _scaleAnimations;
20
21 final List<NavItem> _navItems = [
22 NavItem(icon: Icons.speed_rounded, label: 'Speed'),
23 NavItem(icon: Icons.school_rounded, label: 'School'),
24 NavItem(icon: Icons.dashboard_rounded, label: 'Home'),
25 NavItem(icon: Icons.notifications_rounded, label: 'Alerts'),
26 NavItem(icon: Icons.settings_rounded, label: 'Settings'),
27 ];
28
29 @override
30 void initState() {
31 super.initState();
33 }
34
36 _animationControllers = List.generate(
37 _navItems.length,
38 (index) => AnimationController(
39 duration: const Duration(milliseconds: 50),
40 vsync: this,
41 ),
42 );
43
44 _scaleAnimations = _animationControllers.map((controller) {
45 return Tween<double>(begin: 1.0, end: 0.85).animate(
46 CurvedAnimation(
47 parent: controller,
48 curve: Curves.easeInOut,
49 ),
50 );
51 }).toList();
52 }
53
54 @override
55 void dispose() {
56 for (var controller in _animationControllers) {
57 controller.dispose();
58 }
59 super.dispose();
60 }
61
62 void _handleTap(int index) async {
63 await _animationControllers[index].forward();
64 await _animationControllers[index].reverse();
65
66 setState(() {
67 _selectedIndex = index;
68 });
69
70 bool shouldResetToInitialLocation = index == widget.navigationShell.currentIndex;
71 if (index == 2) {
72 shouldResetToInitialLocation = false;
73 }
74
75 widget.navigationShell.goBranch(
76 index,
77 initialLocation: shouldResetToInitialLocation,
78 );
79 }
80
81 @override
82 Widget build(BuildContext context) {
83 return Scaffold(
84 extendBody: false,
85 body: widget.navigationShell,
86 bottomNavigationBar: Container(
87 decoration: BoxDecoration(
88 color: Colors.white,
89 boxShadow: [
90 BoxShadow(
91 color: Colors.black.withValues(alpha:0.04),
92 blurRadius: 16,
93 offset: const Offset(0, -4),
94 ),
95 BoxShadow(
96 color: Colors.black.withValues(alpha:0.02),
97 blurRadius: 4,
98 offset: const Offset(0, -2),
99 ),
100 ],
101 ),
102 child: SafeArea(
103 child: Container(
104 height: 70.sp,
105 padding: EdgeInsets.symmetric(horizontal: 8.sp),
106 child: Row(
107 mainAxisAlignment: MainAxisAlignment.spaceAround,
108 children: List.generate(
109 _navItems.length,
110 (index) => _buildNavItem(index),
111 ),
112 ),
113 ),
114 ),
115 ),
116 );
117 }
118
119 Widget _buildNavItem(int index) {
120 bool isSelected = _selectedIndex == index;
121 bool isCenter = index == 2;
122 final item = _navItems[index];
123
124 return GestureDetector(
125 onTapDown: (_) => _animationControllers[index].forward(),
126 onTapUp: (_) {
127 _animationControllers[index].reverse();
128 _handleTap(index);
129 },
130 onTapCancel: () => _animationControllers[index].reverse(),
131 child: ScaleTransition(
132 scale: _scaleAnimations[index],
134 width: 45.sp,
135 child: Column(
136 mainAxisSize: MainAxisSize.min,
137 children: [
138 AnimatedContainer(
139 duration: const Duration(milliseconds: 50),
140 curve: Curves.easeInOut,
141 height: 40.sp,
142 width: 40.sp,
143 decoration: BoxDecoration(
144 gradient: isCenter
145 ? LinearGradient(
146 colors: isSelected
147 ? [
150 ]
151 : [
152 ColorPalette.lightGreen.withValues(alpha:0.5),
153 ColorPalette.darkGreen.withValues(alpha:0.5),
154 ],
155 begin: Alignment.topLeft,
156 end: Alignment.bottomRight,
157 )
158 : null,
159 color: !isCenter && isSelected
160 ? ColorPalette.lightGreen.withValues(alpha:0.1)
161 : null,
162 shape: BoxShape.circle,
163 boxShadow: isSelected && isCenter
164 ? [
165 BoxShadow(
166 color: ColorPalette.lightGreen.withValues(alpha:0.3),
167 blurRadius: 8,
168 offset: const Offset(0, 2),
169 ),
170 ]
171 : [],
172 ),
173 child: Icon(
174 item.icon,
175 size: isSelected ? 26.sp : 24.sp,
176 color: isCenter
177 ? Colors.white
178 : isSelected
180 : ColorPalette.grey.withValues(alpha:0.5),
181 ),
182 ),
183 ],
184 ),
185 ),
186 ),
187 );
188 }
189}
190
191class NavItem {
192 final IconData icon;
194
195 NavItem({required this.icon, required this.label});
196}
override void initState()
override void dispose()
class App extends StatefulWidget build(BuildContext context)
Definition app.dart:31
AuthGuard _()
static const lightGreen
static const darkGreen
static const grey
final IconData icon
Definition nav_bar.dart:192
NavItem({required this.icon, required this.label})
final String label
Definition nav_bar.dart:193
final StatefulNavigationShell navigationShell
Definition nav_bar.dart:8
override State< NavBar > createState()
const NavBar(this.navigationShell, {super.key, this.body})
final Widget child
final EdgeInsets padding
class Partner String
final Color color
Definition failures.dart:1
void _initializeAnimations()
Definition nav_bar.dart:35
late List< Animation< double > > _scaleAnimations
Definition nav_bar.dart:19
class NavBar extends StatefulWidget _selectedIndex
final List< NavItem > _navItems
Definition nav_bar.dart:21
void _handleTap(int index) async
Definition nav_bar.dart:62
late List< AnimationController > _animationControllers
Definition nav_bar.dart:18
Widget _buildNavItem(int index)
Definition nav_bar.dart:119
class UnloadingCollectionItem extends StatefulWidget isSelected
final String label
style SizedBox(height:2.h)
style Column(crossAxisAlignment:CrossAxisAlignment.end, children:[Container(padding:EdgeInsets.symmetric(horizontal:8.w, vertical:4.h), decoration:BoxDecoration(color:ColorPalette.tiffanyBlue.withValues(alpha:0.1), borderRadius:BorderRadius.circular(12),), child:Text(collection.type ?? '', style:Theme.of(context).textTheme.bodySmall?.copyWith(color:ColorPalette.tiffanyBlue, fontWeight:FontWeight.bold,),),),],)