如何在 Xamarin Forms 中处理/取消后退导航 [英] How to handle/cancel back navigation in Xamarin Forms

查看:105
本文介绍了如何在 Xamarin Forms 中处理/取消后退导航的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过覆盖 OnBackButtonPressed 来使用后退导航,但不知何故它根本没有被调用.我正在使用 ContentPage 和最新的 1.4.2 版本.

解决方案

好吧,几个小时后我想通了这个.它分为三个部分.

#1 在 android 上处理硬件后退按钮.这个很简单,覆盖 OnBackButtonPressed.请记住,这仅适用于硬件后退按钮和 android.它不会处理导航栏后退按钮.如您所见,我在退出页面之前尝试通过浏览器返回,但您可以放入任何需要的逻辑.

 protected override bool OnBackButtonPressed(){如果(_browser.CanGoBack){_browser.GoBack();返回真;}别的{//等待 Navigation.PopAsync(true);base.OnBackButtonPressed();返回真;}}

#2 iOS 导航返回按钮.这个真的很棘手,如果你环顾网络,你会发现几个用新的自定义按钮替换后退按钮的例子,但几乎不可能让它看起来像你的其他页面.在本例中,我制作了一个位于普通按钮顶部的透明按钮.

[程序集:ExportRenderer(typeof(MyAdvantagePage), typeof(MyAdvantagePageRenderer))]命名空间 Advantage.MyAdvantage.MobileApp.iOS.Renderers{公共类 MyAdvantagePageRenderer :Xamarin.Forms.Platform.iOS.PageRenderer{公共覆盖无效 ViewWillAppear(布尔动画){base.ViewWillAppear(动画);if (((MyAdvantagePage)Element).EnableBackButtonOverride){SetCustomBackButton();}}私有无效 SetCustomBackButton(){UIButton btn = new UIButton();btn.Frame = new CGRect(0, 0, 50, 40);btn.BackgroundColor = UIColor.Clear;btn.TouchDown += (sender, e) =>{//无论您的自定义后退按钮单击处理如果 (((MyAdvantagePage)Element)?.CustomBackButtonAction != null){((MyAdvantagePage)元素)?.CustomBackButtonAction.Invoke();}};NavigationController.NavigationBar.AddSubview(btn);}}}

Android,很棘手.在旧版本和未来版本的表单中,一旦修复,您可以像这样简单地覆盖 OnOptionsItemselected

 public override bool OnOptionsItemSelected(IMenuItem item){//检查当前物品id//等于后退按钮 id如果 (item.ItemId == 16908332){//检索当前的 xamarin 表单页面实例var currentpage = (MyAdvantagePage)Xamarin.Forms.Application.当前.MainPage.Navigation.NavigationStack.LastOrDefault();//检查页面是否已订阅//自定义后退按钮事件if (currentpage?.CustomBackButtonAction != null){//调用自定义后退按钮操作currentpage?.CustomBackButtonAction.Invoke();//并禁用默认的后退按钮操作返回假;}//如果它没有订阅,那么继续//使用默认的后退按钮操作返回 base.OnOptionsItemSelected(item);}别的{//因为它不是后退按钮//点击,将事件传递给base返回 base.OnOptionsItemSelected(item);}}

但是,如果您使用的是 FormsAppCompatActivity,那么您需要在 MainActivity 中添加到您的 OnCreate 以设置您的工具栏:

Android.Support.V7.Widget.Toolbar toolbar = this.FindViewById(Resource.Id.toolbar);SetSupportActionBar(工具栏);

等等!如果您的 .Forms 版本太旧或版本太新,则会出现工具栏为空的错误.如果发生这种情况,我让它工作以制定最后期限的方式是这样的.在 MainActivityOnCreate 中:

 MobileApp.Pages.Articles.ArticleDetail.androdAction = () =>{Android.Support.V7.Widget.Toolbar toolbar = this.FindViewById(Resource.Id.toolbar);SetSupportActionBar(工具栏);};

ArticleDetail 是一个页面,而 androidAction 是一个 Action,如果我的页面上的平台是 Android,我会在 OnAppearing 上运行它.此时,在您的应用中,工具栏将不再为空.

还有几个步骤,我们上面制作的 iOS 渲染使用您需要添加到您为其制作渲染器的任何页面的属性.我正在为我创建的 MyAdvantagePage 类制作它,它实现了 ContentPage .所以在我的 MyAdvantagePage 类中我添加了

public Action CustomBackButtonAction { get;放;}公共静态只读 BindableProperty EnableBackButtonOverrideProperty =BindableProperty.Create(nameof(EnableBackButtonOverride),类型(布尔),typeof(MyAdvantagePage),错误的);///<总结>///获取或设置自定义后退按钮覆盖状态///</总结>public bool EnableBackButtonOverride{得到{返回(布尔)GetValue(EnableBackButtonOverrideProperty);}放{SetValue(EnableBackButtonOverrideProperty, value);}}

现在这一切都完成了,我可以在我的任何 MyAdvantagePage 上添加这个

<预><代码>:this.EnableBackButtonOverride = true;this.CustomBackButtonAction = async() =>{如果(_browser.CanGoBack){_browser.GoBack();}别的{等待 Navigation.PopAsync(true);}};

这应该是让它在 Android 硬件上工作的一切,并为 android 和 iOS 导航回来.

I tried to use the back navigation by overriding OnBackButtonPressed, but somehow it wasn't get called at all. I am using the ContentPage and the latest 1.4.2 release.

解决方案

Alright, after many hours I figured this one out. There are three parts to it.

#1 Handling the hardware back button on android. This one is easy, override OnBackButtonPressed. Remember, this is for a hardware back button and android only. It will not handle the navigation bar back button. As you can see, I was trying to back through a browser before backing out of the page, but you can put whatever logic you need in.

  protected override bool OnBackButtonPressed()
    {
        if (_browser.CanGoBack)
        {
            _browser.GoBack();
            return true;
        }
        else
        {
            //await Navigation.PopAsync(true);
            base.OnBackButtonPressed();
            return true;
        }
    }

#2 iOS navigation back button. This one was really tricky, if you look around the web you'll find a couple examples of replacing the back button with a new custom button, but it's almost impossible to get it to look like your other pages. In this case I made a transparent button that sits on top of the normal button.

[assembly: ExportRenderer(typeof(MyAdvantagePage), typeof

(MyAdvantagePageRenderer))]
namespace Advantage.MyAdvantage.MobileApp.iOS.Renderers
{
    public class MyAdvantagePageRenderer : Xamarin.Forms.Platform.iOS.PageRenderer
    {
        public override void ViewWillAppear(bool animated)
        {
            base.ViewWillAppear(animated);

            if (((MyAdvantagePage)Element).EnableBackButtonOverride)
            {
                SetCustomBackButton();
            }
        }
        private void SetCustomBackButton()
        {
            UIButton btn = new UIButton();
            btn.Frame = new CGRect(0, 0, 50, 40);
            btn.BackgroundColor = UIColor.Clear;

            btn.TouchDown += (sender, e) =>
            {
                // Whatever your custom back button click handling
                if (((MyAdvantagePage)Element)?.
                CustomBackButtonAction != null)
                {
                    ((MyAdvantagePage)Element)?.
                       CustomBackButtonAction.Invoke();
                }
            };
            NavigationController.NavigationBar.AddSubview(btn);
        }
    }
}

Android, is tricky. In older versions and future versions of Forms once fixed, you can simply override the OnOptionsItemselected like this

       public override bool OnOptionsItemSelected(IMenuItem item)
    {
        // check if the current item id 
        // is equals to the back button id
        if (item.ItemId == 16908332)
        {
            // retrieve the current xamarin forms page instance
            var currentpage = (MyAdvantagePage)
            Xamarin.Forms.Application.
            Current.MainPage.Navigation.
            NavigationStack.LastOrDefault();

            // check if the page has subscribed to 
            // the custom back button event
            if (currentpage?.CustomBackButtonAction != null)
            {
                // invoke the Custom back button action
                currentpage?.CustomBackButtonAction.Invoke();
                // and disable the default back button action
                return false;
            }

            // if its not subscribed then go ahead 
            // with the default back button action
            return base.OnOptionsItemSelected(item);
        }
        else
        {
            // since its not the back button 
            //click, pass the event to the base
            return base.OnOptionsItemSelected(item);
        }
    }

However, if you are using FormsAppCompatActivity, then you need to add onto your OnCreate in MainActivity this to set your toolbar:

Android.Support.V7.Widget.Toolbar toolbar = this.FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
            SetSupportActionBar(toolbar);

But wait! If you have too old a version of .Forms or too new version, a bug will come up where toolbar is null. If this happens, the hacked together way I got it to work to make a deadline is like this. In OnCreate in MainActivity:

        MobileApp.Pages.Articles.ArticleDetail.androdAction = () =>
        {
            Android.Support.V7.Widget.Toolbar toolbar = this.FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
            SetSupportActionBar(toolbar);
        };

ArticleDetail is a Page, and androidAction is an Action that I run on OnAppearing if the Platform is Android on my page. By this point in your app, toolbar will no longer be null.

Couple more steps, the iOS render we made above uses properties that you need to add to whatever page you are making the renderer for. I was making it for my MyAdvantagePage class that I made, which implements ContentPage . So in my MyAdvantagePage class I added

public Action CustomBackButtonAction { get; set; }

        public static readonly BindableProperty EnableBackButtonOverrideProperty =
               BindableProperty.Create(
               nameof(EnableBackButtonOverride),
               typeof(bool),
               typeof(MyAdvantagePage),
               false);

        /// <summary>
        /// Gets or Sets Custom Back button overriding state
        /// </summary>
        public bool EnableBackButtonOverride
        {
            get
            {
                return (bool)GetValue(EnableBackButtonOverrideProperty);
            }
            set
            {
                SetValue(EnableBackButtonOverrideProperty, value);
            }
        }

Now that that is all done, on any of my MyAdvantagePage I can add this

:


 this.EnableBackButtonOverride = true;
            this.CustomBackButtonAction = async () =>
            {
                if (_browser.CanGoBack)
                {
                    _browser.GoBack();
                }
                else
                {
                    await Navigation.PopAsync(true);
                }
            };

That should be everything to get it to work on Android hardware back, and navigation back for both android and iOS.

这篇关于如何在 Xamarin Forms 中处理/取消后退导航的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆