Flutter – go_route, shellroute with , popscope problem with bottomnavigation

I have a problem for which I haven’t seen a solution anywhere yet.

I’m using go_route for routing, where I also use shellroute to generate a bottomnavigatorbar in some given paths, but I want it to work like for example on Instagram, so that when I have the functionality of a given page where the bottomnavigatorbar is generated, I want it to remember the given paths where it was before, so that it doesn’t follow exactly the structure of go_route, so that when a user goes for example to /, then to /search and then to /profile, so when he clicks the back button, it first moves him to /search and then to /, but once he’s in the / path, for example, he clicks on /search, again on /, so the back button from the / directory moves him to /search, just where he was before, I solve this in the bottomnavigation back_button_interceptor, where I check the back button and the popscope function, when I finally shut down the application, but the problem occurs when I’m in the / directory

This is a piece of my go_route
`

const String rootRoute = '/';
final GlobalKey<NavigatorState> navigatorKey = GlobalKey();

final GoRouter router = GoRouter(
    debugLogDiagnostics: true,
    errorBuilder: (context, state) => ErrorScreen(state.error),
    initialLocation: rootRoute,
    navigatorKey: navigatorKey,

    routes: <RouteBase>[
       ShellRoute(
        //navigatorKey: _rootNavigatorKey,
        builder: (BuildContext context, GoRouterState state, Widget child) {
          return MultiBlocProvider(
            providers: [
              BlocProvider.value(value: _authBloc),
              BlocProvider.value(value: _authorizedTokenCubit),
              BlocProvider.value(value: _signInUserCubit),
            ],
            child: BlocBuilder<AuthorizedTokenCubit, AuthorizedTokenState>(
              builder: (context, authState) {
                if (authState is AuthorizedTokenSuccess) {
                 return BlocBuilder<SignInUserCubit, SignInUserState>(
                    builder: (context, SignInState) {

                      if (state.uri.path == '/' || state.uri.path == '/search' || (SignInState is SignInUserSuccess && state.uri.pathSegments.length == 1)) {
                        return ScaffoldWithNavBar(child: child);
                      } else {
                        return child; // No ScaffoldWithNavBar for WelcomePage
                      }
                    }
                  );
                  return child;
                } else {
                  return child; // No ScaffoldWithNavBar for WelcomePage
                }
              },
            ),
          );
        },
        routes: <RouteBase>[
        GoRoute(
          path: '/',
          builder: (BuildContext context, GoRouterState state) {
            return MultiBlocProvider(
                providers: [
                  BlocProvider.value(value: _authBloc),
                  BlocProvider.value(value: _authorizedTokenCubit),
                ],
                child: BlocBuilder<AuthorizedTokenCubit, AuthorizedTokenState>(
                    builder: (context, state) {
                  if (state is AuthorizedTokenSuccess) {
                    return HomePage();
                  } else {
                    return WelcomePage();
                  }
                }));
          },
          routes: <RouteBase>[
            GoRoute(
                path: 'signin',
                builder: (BuildContext context, GoRouterState state) {
                  return MultiBlocProvider(providers: [
                    BlocProvider.value(value: _authBloc),
                  ], child: SignInPage());
                },
                routes: [
                  GoRoute(
                    path: 'forgottenpassword',
                    builder: (BuildContext context, GoRouterState state) {
                      return MultiBlocProvider(
                          providers: [
                            BlocProvider.value(value: _authBloc),
                            BlocProvider.value(value: _authorizedTokenCubit),
                          ],
                          child: BlocBuilder<AuthorizedTokenCubit,
                              AuthorizedTokenState>(builder: (context, state) {
                            return ForgottenPasswordPage();
                          }));
                    },
                  ),
                ]),
            
            GoRoute(
              path: 'forgottenpasswordlink',
              builder: (BuildContext context, GoRouterState state) {
                return MultiBlocProvider(providers: [
                  BlocProvider.value(value: _authBloc),
                  BlocProvider.value(value: _injectDataCubit),

                ], child: ForgottenPasswordLinkPage());
              },
            ),
             GoRoute(
              path: 'search',
              builder: (BuildContext context, GoRouterState state) {
                // return MultiBlocProvider(providers: [
                //   BlocProvider.value(value: _searchCubit),
                // ], child: Search());
                return Search();
              },
            ),
           );

Where I implement ScaffoldWithNavBar which is bottomnavigation, this works fine for me, it creates where it should, the problem is though, in battomnavigation.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:go_router/go_router.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:back_button_interceptor/back_button_interceptor.dart';

import '../../router/models/routes.dart';

class ScaffoldWithNavBar extends StatefulWidget {
  /// Constructs an [ScaffoldWithNavBar].
  final Widget child;

  const ScaffoldWithNavBar({
    required this.child,
    super.key,
  });

  /// The widget to display in the body of the Scaffold.
  /// In this sample, it is a Navigator.

  @override
  _ScaffoldWithNavBarState createState() => _ScaffoldWithNavBarState();
}
List<String> navigationHistory = ['/'];

class _ScaffoldWithNavBarState extends State<ScaffoldWithNavBar> {
  int _selectedIndex = 0;
  
  @override
  void initState() {
    super.initState();
    // print('hoj');
    //  print(widget.child);

    BackButtonInterceptor.add(myInterceptor);
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _calculateSelectedIndex(context).then((index) {
      setState(() {
        _selectedIndex = index;
      });
    });
  }

  @override
  void dispose() {
    BackButtonInterceptor.remove(myInterceptor);
    super.dispose();
  }
  

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: <Widget>[   
          PopScope(
            canPop: false,
            child: TextButton(
              onPressed: () async {
                // Your onPressed code here
              },
              child: Text('data'),
            ),
          ),
          Expanded(child: widget.child)
        ],
      ),
      
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.search),
            label: 'Find',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: 'My profile',
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.blue, // Set the color for the selected item
        //unselectedItemColor: Colors.grey, // Set the color for unselected items
        onTap: (int idx) => _onItemTapped(idx, context),
      ),
    );
  }

bool myInterceptor(bool stopDefaultButtonEvent, RouteInfo info) {
    print("BACK BUTTON!"); // Do some stuff.
     // Get and remove the last item from navigationHistory
    
    if (navigationHistory.isNotEmpty) {
      String lastPath = navigationHistory.last;
      print(lastPath);
      GoRouter.of(context).go(lastPath);
      navigationHistory.removeLast();
    }else{
     // SystemNavigator.pop();
    }
    print(navigationHistory);


    return true;
  }

  Future<int> _calculateSelectedIndex(BuildContext context) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final String? username = prefs.getString('username');
    final String location = GoRouterState.of(context).uri.path;
    if (location == '/') {
      return 0;
    }
    if (location == '/search') {
      return 1;
    }
    if(username != null){
      if (location.contains(username)) {
        return 2;
      }else{
        return 0;
      }
    }
    return 0;
  }

  void _onItemTapped(int index, BuildContext context) async{
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final String? username = prefs.getString('username');
    final String currentPath = GoRouterState.of(context).uri.path;
    print(currentPath);
    setState(() {
      _selectedIndex = index;

      // Ensure '/' is always the first entry in navigationHistory
      if (!navigationHistory.contains('/')) {
        navigationHistory.insert(0, '/');
      }

      // Remove currentPath if it already exists in navigationHistory to ensure uniqueness
      if(currentPath != '/'){
        navigationHistory.remove(currentPath);
      }

      // Insert currentPath at the beginning of navigationHistory
      if (currentPath != '/') {
        if (username != null)
        if(!((index == 1 && currentPath == RoutePaths.search) || (index == 2 && currentPath == '/' + username))){
          navigationHistory.insert(1, currentPath); // Insert after '/' if it's not already there
        }
      }

      // Limit navigationHistory to 3 unique paths
      if (navigationHistory.length > 3) {
        navigationHistory.removeLast();
      }
    });
    print(navigationHistory);

    switch (index) {
      case 0:
        GoRouter.of(context).go(RoutePaths.home);
        break;
      case 1:
        GoRouter.of(context).go(RoutePaths.search);
        //context.pushReplacement(RoutePaths.search);
        //GoRouter.of(context).go(RoutePaths.search);
        break;
      case 2:
        if (username != null) {
         context.push('/' + username);
        } else {
          GoRouter.of(context).go(RoutePaths.home);
        }
        break;
    }
  }
}

Here you can see my bottomnavigation code but the strange thing is that the whole function works as it should, when I comment out where I am inserting the page I am on, then it works as it should and in the current context the application doesn’t close, but as soon as I include widget.child in there it doesn’t work Expanded(child: widget.child)

I’ve tried many options but no matter what I’ve searched and tried different options, nothing works as it should, I use go_router: ^12.1.3

New contributor

Filip Brablec is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật