Search code examples
iosxamarinxamarin.formsnavigationbarmaster-detail

Show "Back to Menu" Button in iOS NavigationBar with Xamarin.Forms


I'm trying to build a cross-platform app using C# and Xamarin.Forms. It contains a slide-out menu implemented in form of a MasterDetailPage. While on Android there is a button with the app icon in the top left corner, which toggles the slide-out page, there is no such navigation bar item on iOS.

I broke it down to the following minimum example derived from the Xamarin solution template "Blank App (Xamarin.Forms Shared)" and replacing the implementation of the App-class:

public class App
{
    static MasterDetailPage MDPage;

    public static Page GetMainPage()
    {
        return new NavigationPage(
            MDPage = new MasterDetailPage {
                Master = new ContentPage {
                    Title = "Master",
                    Content = new StackLayout {
                        Children = { Link("A"), Link("B"), Link("C") }
                    },
                },
                Detail = new ContentPage { Content = new Label { Text = "A" } },
            });
    }

    static Button Link(string name)
    {
        var button = new Button { Text = name };
        button.Clicked += delegate {
            MDPage.Detail = new ContentPage { Content = new Label { Text = name } };
            MDPage.IsPresented = false;
        };
        return button;
    }
}

The solution as well as resulting screenshots can be found at GitHub.

My idea was to add such a "menu" or "back" button in the iOS-specific code modifying the window.RootViewController.NavigationController.NavigationBar within the AppDelegate class. But window.RootViewController.NavigationController is null.

Replacing the return type of GetMainPage() by NavigationPage instead of Page does not help.

I could add toolbar items via MDPage.ToolbarItems.Add(...), but they appear in the top right corner.


Solution

  • I finally found a solution. The code basically needs two minor corrections:

    1. Wrap all DetailPages in a NavigationPage, but not the MasterDetailPage (see #1, #2 and #3 below).
    2. Add an Icon to the MasterPage when on iOS (see #4 below). Don't forget to a the actual PNG(!) to the iOS resources.

    The minimum working example is as follows:

    public static class App
    {
        static MasterDetailPage MDPage;
    
        public static Page GetMainPage()
        {
            return MDPage = new MasterDetailPage { // #1
                Master = new ContentPage {
                    Title = "Master",
                    Icon = Device.OS == TargetPlatform.iOS ? "menu.png" : null, // #4
                    Content = new StackLayout {
                        Children = { Link("A"), Link("B"), Link("C") }
                    },
                },
                Detail = new NavigationPage(new ContentPage { Content = new Label { Text = "A" } }), // #2
            };
        }
    
        static Button Link(string name)
        {
            var button = new Button { Text = name };
            button.Clicked += delegate {
                MDPage.Detail = new NavigationPage(new ContentPage { Content = new Label { Text = name } }); // #3
                MDPage.IsPresented = false;
            };
            return button;
        }
    }