在 android 上防止通过 xamarin 表单中的硬件后退按钮关闭

Prevent closing by hardware back button in xamarin forms on android

我想通过在 android 上按 xamarin 表单中的硬件后退按钮来防止关闭应用程序。

我希望您可以使用应用程序中的硬件后退按钮进行导航(有效),但不想在到达导航堆栈中的第一页时退出。

我试过在xamarin forms中使用OnSleep事件,但是这里我无法取消退出。

我还尝试在 android 中捕捉后退按钮:

    public override void OnBackPressed()
    {
        //base.OnBackPressed();
    }

但是在使用xamarin forms时,我不知道当前显示的是哪个页面。所以我不知道是否允许导航返回

这是适用于 Android 的解决方案。
在应用程序中引入一个计数器 class 并随着每个 OnStart 递增它并随着每个 OnStop 递减它,当计数器为 1 你'我会知道你已经到了最后 activity.

不用说,使用基础 activity 实现,这样您就不必复制过去的样板代码。

它适用于评估 NavigationStack(当您使用 NavigationPage 时)。

在我的 Activity 中,我覆盖了 OnBackPressed

public override void OnBackPressed()
{
    if(App.Instance.DoBack)
    {
        base.OnBackPressed();
    }
}

在我的 xamarin forms 应用程序中(App.Instance(它是一个单例)),我将像这样评估当前页面的 NavigationStack。

public bool DoBack
{
    get
    {
        NavigationPage mainPage = MainPage as NavigationPage;
        if (mainPage != null)
        {
            return mainPage.Navigation.NavigationStack.Count > 1;
        }
        return true;                
    }
}

当NavigationStack只剩下一页时,我不会调用base.OnBackPressed,这样我就不会关闭应用程序。

![测试]

下面是 Xamarin Forms MasterDetail 页面场景的代码...

    public bool DoBack
    {
        get
        {
            MasterDetailPage mainPage = App.Current.MainPage as MasterDetailPage;

            if (mainPage != null)
            {    
                bool canDoBack = mainPage.Detail.Navigation.NavigationStack.Count > 1 || mainPage.IsPresented;

                // we are on a top level page and the Master menu is NOT showing
                if (!canDoBack)
                {
                    // don't exit the app just show the Master menu page
                    mainPage.IsPresented = true;
                    return false; 
                }
                else
                {
                    return true;
                }                    
            }
            return true;
        }
    }

只要在你想阻止的页面中给一个空白调用,比如

protected override bool OnBackButtonPressed()
{
return true;
}

这将阻止 XF-Droid 中的后退按钮。

提出的解决方案可以很好地工作,但我不喜欢"static property exposure"解决问题。此外,我不喜欢使用 "properties as methods" 解决方案,尤其是当涉及到很多逻辑时。

这里的主要问题是我们如何处理 Xamarin.Forms.Application class.

中的 OnBackButton() 方法

如何以更优雅的方式做同样的事情?

首先,您需要像这样扩展 Xamarin.Forms.Application class:

namespace YourNameSpace
{
    public class Application : Xamarin.Forms.Application
    {
        #region Public Methods

        public bool HandleBackButton()
        {
            return OnBackPressed();
        }

        #endregion

        #region Application Methods

        protected virtual bool OnBackPressed()
        {
            return false;
        }

        #endregion
    }
}

您的应用程序实施现在将使用此 class 作为基础 class。请记住相应地修改您的 xaml 和 xaml.cs:

<common:Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:common="clr-namespace:YourNameSpace"
             x:Class="YourNameSpace.App">
</common:Application>

在您的 App.cs 实现中,您现在可以覆盖 OnBackButton() 方法。

public partial class App : YourNameSpace.Application
{
    #region Constructors

    public App()
    {
        InitializeComponent();
    }

    #endregion

    #region App Methods

    protected override bool OnBackPressed()
    {
        // Handle when the back button is pressed
        return false;
    }

    #endregion
}

然后你需要稍微改变你的 Activity class 实现。

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    #region Constants and Fields

    private App _app;

    #endregion

    #region Activity Methods

    protected override void OnCreate(Bundle bundle)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;

        base.OnCreate(bundle);

        global::Xamarin.Forms.Forms.Init(this, bundle);

        _app = new App();
        LoadApplication(_app);
    }

    public override void OnBackPressed()
    {
        if(!_app.HandleBackButton())
            base.OnBackPressed();
    }

    #endregion
}

扩展 Chris 的答案,因为现在没有 App.Instance,并且无法在平台代码中以静态方式访问 App

1. App.xaml.cs 在共享项目中

public bool DoBack 
{
    get 
    {
        return MainPage.Navigation.NavigationStack.Count > 1;
    }
}

2.MainActivity.cs 在 Android 项目中

  • 在class中声明一个变量:
App app;
  • OnCreate(Bundle bundle) 中将 LoadApplication(new App()); 更改为:
app = new App();
LoadApplication(app);
  • 覆盖 OnBackPressed() 方法:
public override void OnBackPressed()
{
    if (app.DoBack)
    {
        base.OnBackPressed();
    }
}

您可以使用这个 nuget chd.hwBackButtonManager nuget

github project