使用Xamarin.Forms在iOS NavigationBar中显示“返回菜单”按钮

8
我正在尝试使用C#和Xamarin.Forms构建一个跨平台应用程序。它包含一个以MasterDetailPage形式实现的侧滑菜单。在Android上,有一个位于左上角的带有应用程序图标的按钮,可切换侧滑页面,但是在iOS上没有这样的导航栏项目。
我将其简化为以下最小示例,源自于Xamarin解决方案模板“空白应用程序(Xamarin.Forms共享)”,并替换了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;
    }
}

解决方案以及相关的截图可以在GitHub中找到。
我的想法是在iOS特定的代码中,在AppDelegate类中修改window.RootViewController.NavigationController.NavigationBar,添加一个"菜单"或"返回"按钮。但是window.RootViewController.NavigationController为空。
GetMainPage()的返回类型从Page改为NavigationPage并不能解决问题。
我可以通过MDPage.ToolbarItems.Add(...)来添加工具栏项,但它们会出现在顶部的右侧角落。
3个回答

5

TL;DR

如果要在 iOS 中显示返回按钮,你需要将 Detail 页面包装在一个 NavigationPage 中。


以下是我构建应用程序的示例。

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

现在,您已经完成了这个步骤,您的导航抽屉将按预期进行操作,您的操作栏也将如此。当您想要在应用程序中导航时,您可以使用静态定义的“Navigation”。
await App.Navigation.PushAsync(new FooPage());
// or
await App.Navigation.PopAsync();

如果按照我上面所做的操作,那个视频里演示的就是默认行为。你的“FirstPage”将会是那个带有图片的页面。注意你还需要在主菜单(Master)页面设置图标。 - Chase Florell
这就是它的设计原理,你是想要显示导航菜单吗? - Chase Florell
是的,这就是我想要的:一个打开MainMenu的按钮 - 就像在Android中一样。 - Falko
@SoftSan:在MainActivity中,如果当前IsPresentedtrue,则可以重写OnBackPressed并将其设置为false - Falko
isPresented 用于显示/隐藏菜单(如果我没有误解的话),我在我的 MasterDetail 页面的 NavigateTo 方法中执行。IsPresented = false; 您可以访问 此链接 - SoftSan
显示剩余4条评论

1
我终于找到了解决方案。代码基本上需要两个小修正:
  1. 将所有的DetailPage都包装在一个NavigationPage中,但不包括MasterDetailPage(参见下面的#1、#2和#3)。
  2. 在iOS上为MasterPage添加一个Icon(参见下面的#4)。不要忘记将实际的PNG图片添加到iOS资源中。
最小工作示例如下:
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;
    }
}

最初,我将这个解决方案作为对我的问题的更新发布。刚刚,我决定将其转化为一个明确的答案。 - Falko
这个App类和继承Application类的App类不一样吗? - Krrish
@Krrish:当我发现这个解决方案(在发布问题后不久)时,这是扩展Application类的方法。由于Xamarin.Forms的更新,这种方法发生了很大变化。请参见此处以获取更多关于主细节页面的最新示例。 - Falko
图标是我缺失的关键元素。噼里啪啦,返回按钮出现了。 - Lee McPherson

1
你走在正确的轨道上了,你的NavigatePage需要进入Detail页面。
Detail = new ContentPage { Content = new Label { Text = "A" } }

and

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

会是
Detail = new NavigationPage(new ContentPage { Content = new Label { Text = "A" } })

and

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

这听起来非常有前途。(由于Android不允许同时在屏幕上显示多个导航页面,我将return new NavigationPage(MDPage = ...)替换为return MDPage。) 但现在我在Android上看到一个图标,在iOS上看到了Master页面的标题。而且window.RootViewController.NavigationController仍然为空,因此我不知道如何进一步控制工具栏或返回按钮的外观。 - Falko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接