简体   繁体   中英

GetMidleware not working on bottomNavigationBar - flutter - GetX

i have problem with GetMidleware , so i have 3 item in bottomNavigationBar :

  1. Home
  2. MyTicket
  3. Profile

i want user can acces home without login so i put midleware just on myTicket and Profile , but when i click MyTicket or Profile i still can access that and not redirect to login page.

this is my midleware class:

class AuthMiddleware extends GetMiddleware {
  final authService = Get.find<AuthService>();

  @override
  RouteSettings? redirect(String? route) {
    if (!authService.currentUser.value.isAuthenticated) {
      Get.log(authService.currentUser.value.isAuthenticated.toString());
      return const RouteSettings(name: Routes.LOGIN);
    }
    return null;
  }
}

this is my appPage class:

class AppPages {
   
  static const INITIAL = Routes.ROOT;
   static final routes = [

      GetPage(
      name: _Paths.ROOT,
      page: () => const RootView(),
      binding: RootBinding(),
    ),

      GetPage(
      name: _Paths.HOME,
      page: () => const HomeView(),
      binding: RootBinding(),
    ),
      
      GetPage(
      name: _Paths.MYTICKET,
      page: () => const MyTicketView(),
      binding: RootBinding(),
      middlewares: [AuthMiddleware()],
    ),

     GetPage(
      name: _Paths.PROFILE,
      page: () => const ProfileEditView(),
      binding: RootBinding(),
      middlewares: [AuthMiddleware()],
    ),
   ]
}

this is my root controller:

class RootController extends GetxController {
  final Rx<String> title = Strings.home.obs;
  final Rx<int> currentIndex = 0.obs;
  final authService = Get.find<AuthService>();

  @override
  void onClose() {
    super.dispose();
  }

  List<Widget> pages = [
    const HomeView(),
    const MyTicketView(),
    const ProfileView(),
    // const BlankView(),
  ];

  //get current page for view
  Widget get currentPage => pages[currentIndex.value];

  //change page when bottom nav item is taped
  Future<void> changePage(int _index) async {
    changeTitle(_index);
    if (Get.currentRoute == Routes.ROOT) {
      await changePageInRoot(_index);
    } else {
      await changePageOutRoot(_index);
    }
  }

  Future changeTitle(int index) async {
    switch (index) {
      case 0:
        title.value = Strings.home;
        break;
      case 1:
        title.value = Strings.myTicket;
        break;
      case 2:
        title.value = Strings.myProfile;
        break;
      default:
    }
  }

  //change page if previously page in root
  Future<void> changePageInRoot(int _index) async {
    currentIndex.value = _index;
    await refreshPage(_index);
  }

  //change page if previously page out of root
  Future<void> changePageOutRoot(int _index) async {
    currentIndex.value = _index;
    await refreshPage(_index);
    await Get.offNamedUntil(Routes.ROOT, (Route route) {
      if (route.settings.name == Routes.ROOT) {
        return true;
      }
      return false;
    }, arguments: _index);
  }
}

//call page by index
Future<void> refreshPage(int _index) async {
  switch (_index) {
    case 0:
      {
        Get.find<HomeController>().onInit();
        break;
      }
    case 1:
      {
        Get.find<MyTicketController>().onInit();
        break;
      }
    case 2:
      {
        Get.find<ProfileController>().onInit();
        // Get.find<BlankController>().onInit();
        break;
      }
  }
}

and this is my root view where i put my bottomNavigationBar :

class RootView extends GetView<RootController> {
  const RootView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Obx(
      () => Scaffold(
        appBar: PreferredSize(
          preferredSize: const Size.fromHeight(Dimensions.appBarHeight),
          child: BackWidget(title: controller.title.value),
        ),
        backgroundColor: Colors.white,
        bottomNavigationBar: Material(
          elevation: 10,
          // borderRadius: BorderRadius.circular(20),
          child: BottomNavigationBar(
              selectedIconTheme:
                  const IconThemeData(color: CustomColor.primaryColor),
              selectedLabelStyle: const TextStyle(fontSize: 15),
              selectedItemColor: CustomColor.primaryColor,
              backgroundColor: Colors.white,
              elevation: 25,
              type: BottomNavigationBarType.fixed,
              currentIndex: controller.currentIndex.value,
              onTap: (index) => controller.changePage(index),
              items: [
                bottomNavigationBarItemWidget(
                  'assets/svg/home.svg',
                  Strings.home,
                ),
                bottomNavigationBarItemWidget(
                  'assets/svg/document.svg',
                  Strings.myTicket,
                ),
                bottomNavigationBarItemWidget(
                  'assets/svg/profile.svg',
                  Strings.myProfile,
                ),
              ]),
        ),
        body: controller.currentPage,
      ),
    );
  }

  bottomNavigationBarItemWidget(String icon, String label) {
    return BottomNavigationBarItem(
      icon: SvgPicture.asset(
        icon,
        color: Colors.grey,
        height: 24,
        width: 24,
      ),
      activeIcon: SvgPicture.asset(
        icon,
        color: CustomColor.primaryColor,
        height: 24,
        width: 24,
      ),
      label: label,
      tooltip: label,
    );
  }
}

BottomNavigationBar (also TabBar) doesn't change routes. It's essentially single page. Therefore route middlewares can't be used with them without complications. Instead, you can use the auth check on the respective controllers of the views of navigation bar items. A very good place is in the onReady method of the GetxController s.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM