Mostrar el button "Volver al menu" en iOS NavigationBar con Xamarin.Forms

Estoy intentando build una aplicación multiplataforma usando C # y Xamarin.Forms. Contiene un menu desplegable implementado en forma de un MasterDetailPage . Mientras que en Android hay un button con el ícono de la aplicación en la esquina superior izquierda, que alterna la página de deslizamiento, no hay tal elemento de la barra de navigation en iOS.

Lo desglosé al siguiente ejemplo mínimo derivado de la plantilla de solución de Xamarin "Aplicación en blanco (Xamarin.Forms Shanetworking)" y reemplazando la implementación de la 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; } } 

La solución, así como las capturas de pantalla resultantes se pueden encontrar en GitHub .

Mi idea era agregar un button de "menu" o "atrás" en el código específico de iOS que modifica la window.RootViewController.NavigationController.NavigationBar dentro de la class AppDelegate . Pero window.RootViewController.NavigationController es null .

Reemplazar el tipo de GetMainPage() de GetMainPage() por NavigationPage lugar de la Page no ayuda.

Podría agregar elementos de la barra de herramientas a través de MDPage.ToolbarItems.Add(...) , pero aparecen en la esquina superior derecha .

TL; DR

Esencialmente, su página de Detail debe estar envuelta en un NavigationPage para que el button Atrás aparezca en iOS.


Aquí hay un ejemplo de cómo estructuro mis aplicaciones.

App.cs

  public static INavigation Navigation { get; set; } public static Page GetMainPage(IContainer container) { return new MainPage(); } 

MainPage.cs

 public class MainPage : MasterDetailPage { public MainPage() { Title = "Some Title"; var master = new MainMenu(); var detail = new NavigationPage(new FirstPage()); if (App.Navigation == null) { App.Navigation = detail.Navigation; } Master = master; Detail = detail; } } 

Ahora que lo ha hecho, su cajón de navigation se comportará como se esperaba, y también lo hará su ActionBar.

Cuando desea navegar por la aplicación, usa la Navigation definida estáticamente

 await App.Navigation.PushAsync(new FooPage()); // or await App.Navigation.PopAsync(); 

Tu en el path correcto, tu NavigatePage necesita ir en el Detalle para que

 Detail = new ContentPage { Content = new Label { Text = "A" } } and MDPage.Detail = new ContentPage { Content = new Label { Text = name } }; 

sería

 Detail = new NavigationPage(new ContentPage { Content = new Label { Text = "A" } }) and MDPage.Detail = new NavigationPage(new ContentPage { Content = new Label { Text = name } }); 

Finalmente encontré una solución. El código básicamente necesita dos correcciones menores:

  1. Envuelva todas las DetailPage s en una NavigationPage , pero no el MasterDetailPage (vea # 1, # 2 y # 3 a continuación).
  2. Agregue un Icon al MasterPage cuando MasterPage en iOS (vea el número 4 a continuación). ¡No te olvides de un PNG real (!) Para los resources de iOS.

El ejemplo de trabajo mínimo es el siguiente:

 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; } }