mt-akar / bottom_nav_layout

A quick and powerful Flutter layout with a bottom navbar.
https://pub.dev/packages/bottom_nav_layout
MIT License
34 stars 11 forks source link

Can tabs be switched programmatically? #12

Closed mark8044 closed 2 years ago

mark8044 commented 2 years ago

Can tabs be switched programmatically? Say from a void function elsewhere?

mt-akar commented 2 years ago

Yes. Please refer to the documentation before creating an issue.

This is what you are looking for: https://github.com/m-azyoksul/bottom_nav_layout#page-back-stack

Have a great day.

mark8044 commented 2 years ago

Yes. Please refer to the documentation before creating an issue.

This is what you are looking for: https://github.com/m-azyoksul/bottom_nav_layout#page-back-stack

Have a great day.

@m-azyoksul

But this is to push or pop pages from within each tab correct?

What if I am inside tab 1 and I want to programmatically switch to tab 4? And If I were to do it from a class outside of the bottom navbar would I need someway to access this from the outside world?

mt-akar commented 2 years ago

Your question is confusing me. I will attempt to explain again.

  1. Create a PageStack instance.
  2. Pass that to the BottomNavLayout. Now that PageStack is managing the top level destinations in the layout.
  3. Programmatically switch tabs by calling Push on the PageStack instance. This will navigate you to that page and update the underlying page stack accordingly.

In which context or class you call the Push method does not matter. As long as it is the PageStack that is associated with the BottomNavLayout, the navigation will work. If you need, you can pass the PageStack instance around as a parameter.

mark8044 commented 2 years ago

Your question is confusing me. I will attempt to explain again.

  1. Create a PageStack instance.
  2. Pass that to the BottomNavLayout. Now that PageStack is managing the top level destinations in the layout.
  3. Programmatically switch tabs by calling Push on the PageStack instance. This will navigate you to that page and update the underlying page stack accordingly.

In which context or class you call the Push method does not matter. As long as it is the PageStack that is associated with the BottomNavLayout, the navigation will work. If you need, you can pass the PageStack instance around as a parameter.

What I have is an app with 4 tabs at the bottom, each of those tabs has a series of possible screens within each tab, depending on what the user is doing.

When the user has the app in background the app might be on any given tab or page.

When a push notification comes in and the user clicks on the notification, the app should launch and immediately goto tab 4 (which is the tab holding notification data), but the user might have last been using tab 2 and have 10 screens open within tab 2. Also when it goes to tab 4, it should goto the screen in tab 4 where the user left off (the top most screen in tab 4), basciculy what happens if the user manually clicked on tab 4, it would automatically switch the tab to tab 4 and show the last thing he was looking at on tab 4

So for example what I have done is this:

main.dart

var bottomNavBarGlobalControl = ReorderToFrontExceptFirstPageStack(initialPage: 0);

bottomlayoutnav.dart

...
      pageStack: bottomNavBarGlobalControl,
...
      pages: [
            (navKey) => Navigator(
          key: widget.firstTabNavKey,
          initialRoute: "/",
          onGenerateRoute: (routeSettings) => MaterialPageRoute(
            builder: (context) {
              return const Screen1();
            },
          ),
        ),

respondtopush.dart

bottomNavBarGlobalControl.push(3);   //Nothing actually happens, the tab and screen both stay where the user last left

        var top = bottomNavBarGlobalControl.peek();
        var length = bottomNavBarGlobalControl.length;
        debugPrint('TOP: '+top.toString());                     // this is always 1
        debugPrint('LENGTH: '+length.toString());        // this always 5

bottomNavBarGlobalControl.pop();    // results in error: bad state




What I was thinking might be possible was a direct method to change the active tab, similar to this concept: https://stackoverflow.com/a/67716471

mt-akar commented 2 years ago

What I have is an app with 4 tabs at the bottom, each of those tabs has a series of possible screens within each tab, depending on what the user is doing.

When the user has the app in background the app might be on any given tab or page.

So far, so good.

When a push notification comes in and the user clicks on the notification, the app should launch and immediately goto tab 4 (which is the tab holding notification data), but the user might have last been using tab 2 and have 10 screens open within tab 2. Also when it goes to tab 4, it should goto the screen in tab 4 where the user left off (the top most screen in tab 4), basciculy what happens if the user manually clicked on tab 4, it would automatically switch the tab to tab 4 and show the last thing he was looking at on tab 4

I think I understand this. Seems reasonable.

var bottomNavBarGlobalControl = ReorderToFrontExceptFirstPageStack(initialPage: 0);

I am assuming you are sharing this page stack with other widgets. Still doing good.

pageStack: bottomNavBarGlobalControl,

Awesome. You are setting it to the layout.

pages: [ (navKey) => Navigator( key: widget.firstTabNavKey, initialRoute: "/", onGenerateRoute: (routeSettings) => MaterialPageRoute( builder: (context) { return const Screen1(); }, ), ),

You are not using the library's navKey given to you. Weird but it would still work. Also your navigator always returns Screen1. I assume you push widgets directly instead of using routes. This is fine. Good job.

bottomNavBarGlobalControl.push(3); //Nothing actually happens, the tab and screen both stay where the user last left var top = bottomNavBarGlobalControl.peek(); var length = bottomNavBarGlobalControl.length; debugPrint('TOP: '+top.toString()); // this is always 1 debugPrint('LENGTH: '+length.toString()); // this always 5 bottomNavBarGlobalControl.pop(); // results in error: bad state

This is where I lose you. Not a single comment here is what should really be happening. The code looks good but your allaged outcomes are all wrong. There is some other problem somewhere I do not know and have not seen.

Could you share a minimal, operational version of your code that replicates this problem?

Alternatively, I maybe able to live assist you. Reach me through discord at ViraL#2868

mark8044 commented 2 years ago

OK, here's what I came up with that seems to work, not sure if this is a very clean solution

Maybe this helps someone, but I still feel this isn't a great solution

main.dart

final GlobalKey bottomTabBarNavKey = new GlobalKey();

bottomlayoutnav.dart

...
        BottomNavigationBar(
          key: bottomTabBarNavKey,
...

respondtopush.dart

        final navigationBar = bottomTabBarNavKey.currentWidget as BottomNavigationBar;
        navigationBar.onTap!(3);
Colton127 commented 2 years ago

I can concur with @mark8044 that the documentation https://github.com/m-azyoksul/bottom_nav_layout#page-back-stack does not function correctly for me, either.

My code was as followed: var navigatorPageStack = FirstAndLastPageStack(initialPage: 0);

 return BottomNavLayout(
        pageStack: navigatorPageStack,

navigatorPageStack.add(2); //Attempt to switch to third tab

@mark8044's Code in the post above worked fine for me.

mt-akar commented 2 years ago

Maybe you need to call setState @Colton127? Does that work, could you inform me?

Colton127 commented 2 years ago

Maybe you need to call setState @Colton127? Does that work, could you inform me?

I tried calling setState while calling navigatorPageStack.add, but with no effect.

Keep in mind that this is within my project. When I get a chance, I will review the example project and attempt to implant tab switching into it.

Thank you for your support, and for such a great package, it saved me a lot of time and I'm happy I went with it for my current project.

mt-akar commented 2 years ago

Thank you for the compliments. This might be a real problem in the package I somehow missed. If so, I do not know the cause of it. I will investigate.

mt-akar commented 2 years ago

The package is working as intended. I added a full example for programmatic navigation to the documentation.