dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.27k stars 1.76k forks source link

TabbedPage does not trigger when reselected current tab #17877

Open espritm opened 1 year ago

espritm commented 1 year ago

Description

The TabbedPage provide an event called "CurrentPageChanged", which is triggered when user click on Tab1, then on Tab2, etc.. The TabbedPage does not provide event when user click on Tab1, then on Tab1, and on Tab1 again, etc...

On native Android for instance, with a BottomNavigationView (TabbedPage with tabs at bottom), this event is called OnItemReselectedListener

This documentation says "This listener will also be notified when the currently selected item is reselected, unless an NavigationBarView.OnItemReselectedListener has also been set".

I have been digging up a while and here, we do nothing when a item is selected if its ID is the same as the current selected item id.

I tried to get this event by myself using Handlers, but it seems it is not possible - I couldn't find the solution. I can't find a way to get the reference to that BottomNavigationBar using handlers, so I don't see workaround. Here is my sample https://github.com/espritm/Maui.TabbedPage.OnItemReselected

Steps to Reproduce

  1. Open the sample project
  2. Build and deploy for Android
  3. When clicking on Tab1, then on Tab2, the event "CurrentPageChanged" is triggered

Expected outcome :

  1. When clicking on Tab1, then on Tab1 again, an event "CurrentPageReselected" is triggered.

Actual outcome :

  1. When clicking on Tab1, then on Tab1 again, the event "CurrentPageChanged" is not triggered, and we have no other solution.

Link to public reproduction project repository

https://github.com/espritm/Maui.TabbedPage.OnItemReselected

Version with bug

7.0.92

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

iOS, Android, I was not able test on other platforms

Affected platform versions

No response

Did you find any workaround?

No, tried to use Handlers but could not access to the appropriate instances of native views.

Relevant log output

No response

ghost commented 1 year ago

We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.

BentAHogset commented 7 months ago

Any progress on this? I'm struggling with the same issue...

nord- commented 2 months ago

I'm also interested in the progress of this issue. I would like to navigate to "tab root" if the current tab is selected (again).

LeoJHarris commented 1 week ago

👀

pictos commented 1 week ago

I can't see how this is a bug... If you're in the same page the CurrentPageChanged shouldn't trigger, as it does. I think what you want is a new event or Command that will fire when that happens.

For now, you can implement your own action customizing the Handler

LeoJHarris commented 1 week ago

@pictos Agree, seems like more of a feature request then anything else. If it can be handled natively then a handler should work somehow. Probably best continued from the repos' discussions?

etm-ubp commented 6 days ago

Would be happy and greatful to have a sample handler to handle this please. I've not been able to achieve it my self unfortunately.

espritm commented 6 days ago

Would be happy and greatful to have a sample handler to handle this please. I've not been able to achieve it my self unfortunately.

Same for me : I did not succeed to create the handler to access this native OnItemReselectedListener event.. I would be thankful to have some help please. Thanks a lot for your time

pictos commented 5 days ago

There you go


using static System.Reflection.BindingFlags;

    // TabbedPage.Loaded event 
    void OnLoaded(object? sender, EventArgs e)
    {
#if ANDROID

        if (Handler is null)
            return;

                            // BindingFlags
        var flags = Instance | NonPublic;

        Type tabbedPageType = typeof(Microsoft.Maui.Controls.TabbedPage);

        // Get the field information for the _tabbedPageManager field
        var tabManager = tabbedPageType.GetField("_tabbedPageManager", flags)?.GetValue(this);

        Debug.Assert(tabManager is not null);

        var tabLayout = tabManager.GetType().GetField("_tabLayout", flags)?.GetValue(tabManager);

        if (tabLayout is Google.Android.Material.Tabs.TabLayout tLayout)
        {
            tLayout.TabReselected += (s, e) =>
            {

                var item = e.Tab;
                _ = 1;
            };

            return;
        }

        var bottomNavigation = tabManager.GetType().GetField("_bottomNavigationView", flags)?.GetValue(tabManager);

        if (bottomNavigation is Google.Android.Material.BottomNavigation.BottomNavigationView bNav)
        {
            bNav.ItemReselected += (s, e) =>
            {
                var item = e.Item;
                _ = 1;
            };
        }
#endif
    }

@PureWeen, this is a good case to make public or create some extension points around the TabbedPageManager