How to Detect Tab Click Event in .NET MAUI AppShell with TabBar and Refresh Page on Tab Re-click

67 Views Asked by At

I need to detect tab clicking, for example, when I am on Tab2 and click on Tab2 again, I want to refresh the page, how can I do this? I know that there is no built-in Clicked event for . How can I achieve this?

1

There are 1 best solutions below

0
Jessie Zhang -MSFT On

As a summary, I will post a answer so that it will help others who have similar problems.

For this problem, we can try to use the workaround here.

The steps are as follows:

1.Override the Shell's OnNavigating to trigger PopToRootAsync on Android.

2.Subclass the ShellRenderer for Android and register the BottomView's ItemReselected event. We should register it only once, otherwise we will get multiple events.

using Android.Content;
using Google.Android.Material.BottomNavigation;
using Microsoft.Maui.Controls.Handlers.Compatibility;
using Microsoft.Maui.Controls.Platform.Compatibility;

namespace Your.Namespace;

/// <summary>
/// Shell renderer to fix tab reselection event issue on Android
/// https://github.com/dotnet/maui/issues/15301
/// </summary>
public class AndroidShellRenderer : ShellRenderer
{
    public AndroidShellRenderer(Context context) : base(context)
    {
    }

    protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
    {
        return new CustomShellBottomNavViewAppearanceTracker(this, shellItem);
    }
}

public class CustomShellBottomNavViewAppearanceTracker : ShellBottomNavViewAppearanceTracker
{
    private readonly IShellContext _shellRenderer;
    private readonly ShellItem _shellItem;
    private bool _subscribedItemReselected;

    public CustomShellBottomNavViewAppearanceTracker(IShellContext shellRenderer, ShellItem shellItem)
        : base(shellRenderer, shellItem)
    {
        _shellRenderer = shellRenderer;
        _shellItem = shellItem;
    }

    public override void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
    {
        if (_subscribedItemReselected) return;
        bottomView.ItemReselected += ItemReselected;
        _subscribedItemReselected = true;
    }

    private void ItemReselected(object? sender, EventArgs e)
    {
        (_shellItem as IShellItemController).ProposeSection(_shellItem.CurrentItem);
    }
}

3.Register the newly created ShellRenderer as a Handler for the Shell component

AppShell.xaml.cs

public partial class AppShell : Shell
{
    public AppShell()
    {
        InitializeComponent();
    }

    private bool _isPopToRootInProgress;
    protected override void OnNavigating(ShellNavigatingEventArgs args)
    {
        base.OnNavigating(args);
        if (DeviceInfo.Platform == DevicePlatform.Android
            && args.Source == ShellNavigationSource.ShellSectionChanged
            && args is { Current: not null, Target: not null }
            && args.Current.Location == args.Target.Location
            && !_isPopToRootInProgress
            && CurrentPage.Navigation.NavigationStack.Count > 1)
        {
            _isPopToRootInProgress = true;
            CurrentPage.Navigation.PopToRootAsync().ContinueWith(_ =>
            {
                _isPopToRootInProgress = false;
            });
        }
    }
}

Register handler

     builder.ConfigureMauiHandlers(handlers =>
    {
#if ANDROID
        handlers.AddHandler(typeof(Shell), typeof(Your.Namespace.AndroidShellRenderer))
#endif
    });