[FIXED] Flyout menu not available after navigation in MAUI

Issue

I am taking a Xamarin Forms application and converting it over to MAUI.

In Android, I have found that if I navigate to a different page, I lose my flyout button (hamburger button) in the top navigation bar. I haven’t tried it yet in iOS but I assume it is the same behavior.

Here is how I am navigating to my initial page:

private void LaunchInitialPage(Page page)
{
    FlyoutPage FlyoutPage = new FlyoutPage
    {
        Detail = new NavigationPage(page)
        {
            BarBackgroundColor = Helpers.Colors.BarBackgroundColor,
            BarTextColor = Color.FromArgb("#ffffff")
        },
        Flyout = new MyDrawerMenu(),
        FlyoutLayoutBehavior = FlyoutLayoutBehavior.Popover
    };
    ((App)Application.Current).MainPage = FlyoutPage;
}

The above works like a charm. My page is rendered correctly, and I see the hamburger menu.

Most of the time, I would want to "back" button to show up at the top of the page when they click on an item. And that works. However there are a few pages where a back button doesn’t make sense, so I want it removed and instead display the hamburger menu.

Here is how my navigation looks:

public async Task LaunchNextPage(Page page)
{
    Page mdp = (((App)Application.Current).MainPage as FlyoutPage).Detail;
    NavigationPage np = (NavigationPage)mdp;

    NavigationPage.SetHasBackButton(page, false);
    await np.PushAsync(page, true);
}

This code successfully navigates to the second page. The back button works as expected, and the NavigationPage.SetHasBackButton(page,false) removes the back button from the navigation bar at the top of the screen.

However, I do not see the hamburger menu. I can still swipe over from the left and reveal the menu, but I really want to see the hamburger show up at the top of the page.

I should note that this did work as I expected in Xamarin.Forms. It is only when migrating to MAUI that I am seeing this behavior.

Any help would be greatly appreciated!

Solution

I wasn’t able to find a good way to bring the default hamburger button back on request without clearing the page stack, which I didn’t want to do for all pages. So I was able to get this to work by setting the Title View when needed and replicating the navigation bar.

public async Task LaunchNextPage(Page page)
{
    NavigationPage.SetHasBackButton(page, false);

    var fop = ((App)App.Current).MainPage as FlyoutPage;
    if (fop.Detail.Navigation.NavigationStack?.ToList()?.Count > 0)
    {
        NavigationPage.SetTitleView(this, new NavigationBar());
    }
    else
    {
        // at the beginning of the stack so already showing the burger menu
        NavigationPage.SetTitleView(this, null);
    }

    NavigationPage np = (NavigationPage)fop.Detail;
    await np.PushAsync(page, true);

    if (NavigationPage.GetTitleView(this) != null)
    {
        (NavigationPage.GetTitleView(this) as NavigationBar).Title = page.Title;
    }
}

NavigationBar.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<HorizontalStackLayout
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="NavigationBar" 
    VerticalOptions="CenterAndExpand" 
    HorizontalOptions="FillAndExpand" 
    Spacing="0"
    Padding="0"
    x:Name="this">

    <ImageButton
        x:Name="imgBurger"
        Source="hamburger_menu_icon.png" 
        WidthRequest="24" 
        HeightRequest="24"
        Margin="0,0,36,0"
        Clicked="imgBurger_Clicked"
        />

    <Label
        x:Name="lblNavBarTitle"
        VerticalOptions="Center"
        FontAttributes="Bold"
        FontSize="Medium" />

</HorizontalStackLayout>

NavigationBar.xaml.cs:

public partial class NavigationBar : HorizontalStackLayout
{ 
    public NavigationBar()
    {
        InitializeComponent();
        lblNavBarTitle.TextColor = Color.FromArgb("#FFFFFF");
        BackgroundColor = Color.FromArgb("#000000");
    }

    public string Title
    {
        set
        {
            lblNavBarTitle.Text = value;
        }
    }

    private void imgBurger_Clicked(object sender, EventArgs e)
    {
        var fop = ((App)App.Current).MainPage as FlyoutPage;
        fop.IsPresented = !fop.IsPresented;
    }
}

Hope this helps somebody!

Answered By – Mike Luken

Answer Checked By – Senaida (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published