Reputation: 1
import 'package:flutter/cupertino.dart';
import 'package:flutter_svg/svg.dart';
import 'package:page_transition/page_transition.dart';
import 'package:persistent_bottom_nav_bar/persistent_tab_view.dart';
import 'package:sizer/sizer.dart';
import 'package:abc/Messages/messages.dart';
import 'package:abc/Vehicles/confirmVehicle.dart';
import 'package:abc/Vehicles/qr_scan_page.dart';
import 'package:abc/pages/common_widgets.dart';
import 'package:abc/pages/dashboard.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class PersistantWidget extends StatefulWidget {
const PersistantWidget({super.key});
@override
State<PersistantWidget> createState() => _PersistantWidgetState();
}
class _PersistantWidgetState extends State<PersistantWidget> {
@override
Widget build(BuildContext context) {
PersistentTabController _controller =
PersistentTabController(initialIndex: 0);
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
List<Widget> _buildScreens() {
return [
Dashboard(),
ConfirmVehicle(),
QrScanPage(
toOwnerPage: true,
addNewVehicle: false,
),
Messages(),
// Settings(),
];
}
List<BottomNavigationBarItem> _navBarsItems() {
return [
BottomNavigationBarItem(
label: 'Home',
icon: Container(
height: 2.5.h,
width: 5.5.w,
child: SvgPicture.asset(
"assets/images/dashboard_home.svg",
fit: BoxFit.cover,
width: 23.49,
height: 23.49,
),
),
),
BottomNavigationBarItem(
label: 'Vehicles',
icon: Container(
height: 2.5.h,
width: 5.5.w,
child: SvgPicture.asset(
'assets/images/vehicle.svg',
fit: BoxFit.cover,
width: 23.49,
height: 23.49,
),
),
),
BottomNavigationBarItem(
label: '',
icon: Container(
height: 2.5.h,
width: 5.5.w,
child: SvgPicture.asset(
"",
fit: BoxFit.cover,
width: 23.49,
height: 23.49,
),
),
),
BottomNavigationBarItem(
label: 'Messages',
icon: Container(
height: 2.5.h,
width: 5.5.w,
child: SvgPicture.asset(
'assets/images/message.svg',
fit: BoxFit.cover,
width: 23.49,
height: 23.49,
),
),
),
BottomNavigationBarItem(
label: 'Settings',
icon: Container(
height: 2.5.h,
width: 5.5.w,
child: SvgPicture.asset(
'assets/images/setting.svg',
fit: BoxFit.cover,
width: 23.49,
height: 23.49,
),
),
),
];
}
return Scaffold(
key: _scaffoldKey,
drawer: Drawer(
backgroundColor: Colors.white,
elevation: 16.0,
width: 67.w,
child: DrawerWidget()),
body: Stack(
children: [
PersistentTabView.custom(
context,
controller: _controller,
screens: _buildScreens(),
confineInSafeArea: true,
backgroundColor: Colors.white,
handleAndroidBackButtonPress: true,
onWillPop: (BuildContext? context) async {
return false;
},
resizeToAvoidBottomInset: true,
stateManagement: true,
hideNavigationBarWhenKeyboardShows: true,
screenTransitionAnimation: const ScreenTransitionAnimation(
animateTabTransition: true,
curve: Curves.ease,
duration: Duration(milliseconds: 200),
),
customWidget: CustomNavBarWidget(
items: _navBarsItems(),
selectedIndex: _controller.index,
onItemSelected: (index) {
_controller.index = index;
},
scaffoldKey: _scaffoldKey,
controller: _controller,
),
itemCount: 5,
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 9.h,
width: 18.w,
margin: EdgeInsets.only(top: 6.5.h, left: 2.h, right: 2.h),
child: FloatingActionButton(
backgroundColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50.0),
),
onPressed: () {
_controller.index = 2;
},
highlightElevation: 0,
tooltip: 'Floating Button',
child: SvgPicture.asset(
'assets/images/bottomnav_scan.svg',
height: 9.h,
width: 18.w,
),
elevation: 0,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
))
],
),
);
}
}
class CustomNavBarWidget extends StatelessWidget {
final int selectedIndex;
final List<BottomNavigationBarItem> items;
final ValueChanged<int> onItemSelected;
final GlobalKey<ScaffoldState> scaffoldKey;
final PersistentTabController controller; // Add this line
CustomNavBarWidget({
super.key,
required this.selectedIndex,
required this.items,
required this.onItemSelected,
required this.scaffoldKey,
required this.controller,
});
Widget _buildItem(BottomNavigationBarItem item, bool isSelected) {
return Container(
alignment: Alignment.center,
height: 60.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
child: IconTheme(
data: IconThemeData(size: 26.0, color: Colors.grey),
child: item.icon,
),
),
Padding(
padding: const EdgeInsets.only(top: 5.0),
child: Material(
type: MaterialType.transparency,
child: Text(
item.label ?? "",
style: TextStyle(
color: Colors.grey,
fontFamily: 'Vive Body',
fontWeight: FontWeight.w500,
fontSize: 7.sp),
),
),
)
],
),
);
}
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Container(
width: double.infinity,
height: 60.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: items.map((item) {
int index = items.indexOf(item);
return Flexible(
child: GestureDetector(
onTap: () {
if (index == 4) {
scaffoldKey.currentState!.openDrawer();
} else {
onItemSelected(index);
}
},
child: _buildItem(item, selectedIndex == index),
),
);
}).toList(),
),
),
);
}
}
We are using persistent bottom navigation bar fluter package. It works perfectly fine but when we call a particular page from the side drawer for example 'contact us' then it will redirect us to contact us page but we loose the persistent bottom navigation bar.
But we redirect from the bottom navigation bar we don't loose the bottom navigation bar.
Upvotes: 0
Views: 43
Reputation: 236
It's very simple to achieve.
first let me show you my workaround
An enum that contains all the actions that are performed by sideNavDrawer (don't perform action directly from side nav drawer widget) change them according to your application
enum SideNavActions {
close,
nearByTechnicians,
myRequests,
payments,
support,
rateYourTechnician,
logout,
}
then pass a function into your DrawerWidget like this
class SideNavDrawer extends StatefulWidget {
final Function(SideNavActions) callback; // <--- callback function
const SideNavDrawer({
Key? key,
required this.callback,
}) : super(key: key);
@override
State<SideNavDrawer> createState() => _SideNavDrawerState();
}
now you will call this callback function in your SideNavDrawerItem widget like this (below is an example from my app)
ListTile(
onTap: () {
// this is callback function
widget.callback(SideNavActions.nearByTechnicians);
},
leading: Image.asset(
'assets/icons/map_marker.png',
color: AppColors.white,
width: 25,
height: 25,
),
title: const Text('Nearby Technicians'),
),
now let's go back to your DrawerWidget, you need to pass that callback function into your DrawerWidget like this
drawer: SideNavDrawer(
callback: (p0) {
viewModel.sideNavCallBack(p0);
},
),
now what is viewModel.sideNavCallBack(p0) function, this function will actually listen to your callback function (ignore viewModel because I am following MVVM design pattern) you can write that function into your PersistantWidget
now write your navigation logic in sideNavCallBack function
void sideNavCallBack(SideNavActions action) {
if (action == SideNavActions.close) {
advancedDrawerController.hideDrawer();
} else if (action == SideNavActions.nearByTechnicians) {
advancedDrawerController.hideDrawer();
// just focus on this below function selectPage(index), this function is used to update the page when user click on an item on bottomNavigation bar
selectPage(1);
} else if (action == SideNavActions.myRequests) {
advancedDrawerController.hideDrawer();
_nav.pushNamed(myRequestsViewRoute);
} else if (action == SideNavActions.payments) {
} else if (action == SideNavActions.support) {
advancedDrawerController.hideDrawer();
_nav.pushNamed(supportViewRoute);
} else if (action == SideNavActions.rateYourTechnician) {
} else if (action == SideNavActions.logout) {
logoutAlert();
}
}
Upvotes: 0