Anusha Kulkarni
Anusha Kulkarni

Reputation: 1

Navigate to a different page from the side bar drawer without using the bottom navigation bar using persistent flutter package

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

Answers (1)

Zakwan Ibrahim
Zakwan Ibrahim

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();
    }
  }

have a look of demonstration

Upvotes: 0

Related Questions