簡體   English   中英

覆蓋導航欄后退按鈕單擊 Xamarin.Forms

[英]Override nav bar back button click on Xamarin.Forms

我在 xamarin.forms 中有表格,如果有待保存的數據,我想在用戶單擊導航欄按鈕時顯示彈出消息。 我找到了這個例子,但它不適用於 Xamarin.Forms 5.0

知道怎么做嗎?

我對此進行了快速測試,您可以參考它。

首先,我創建一個 contentpage 並設置CustomBackButtonActionEnableBackButtonOverride以添加導航方法:

public partial class TestPage5 : ContentPage
    {public Action CustomBackButtonAction { get; set; }
        public static readonly BindableProperty EnableBackButtonOverrideProperty = BindableProperty.Create(
            nameof(EnableBackButtonOverride),
            typeof(bool),
            typeof(TestPage5),
            false
            );
          public bool EnableBackButtonOverride {

            get { return (bool)GetValue(EnableBackButtonOverrideProperty); }
            set { SetValue(EnableBackButtonOverrideProperty, value); }
        }
        public TestPage5()
        {
            InitializeComponent();
            EnableBackButtonOverride = true;
            CustomBackButtonAction = async () => { var result = await DisplayAlert("Alert", "Are you Sure?", "Yes", "No");
                if (result)
                { await Navigation.PopAsync(true); }     };
        }  
        }

然后在 ios 上創建渲染器,同時在 android 上覆蓋 OnOptionsItemSelected:

ios(創建一個新的后退按鈕並覆蓋):

[assembly:ExportRenderer(typeof(TestPage5),typeof(MyRenderer))]
namespace My_Forms_Test3.iOS
{
    public class MyRenderer:Xamarin.Forms.Platform.iOS.PageRenderer
    {
        public override void ViewWillAppear(bool animated)
        {
            base.ViewWillAppear(animated);
            if (((TestPage5)Element).EnableBackButtonOverride)
            {
                SetButton();
            }
        }

           private void SetButton()
            {
            var backbuttonimg = UIImage.FromBundle("backarrow.png");
            backbuttonimg = backbuttonimg.ImageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate);
            var backbutton = new UIButton(UIButtonType.Custom)
            { HorizontalAlignment=UIControlContentHorizontalAlignment.Left,
            TitleEdgeInsets=new UIEdgeInsets(11.5f,15f,10f,0f),
            ImageEdgeInsets=new UIEdgeInsets(1f,8f,0f,0f)};
            backbutton.SetTitle("Back", UIControlState.Normal);
            backbutton.SetTitleColor(UIColor.White, UIControlState.Normal);
            backbutton.SetTitleColor(UIColor.LightGray, UIControlState.Highlighted);
            backbutton.Font = UIFont.FromName("HelveticaNeue", (nfloat)17);
            backbutton.SetImage(backbuttonimg, UIControlState.Normal);
            backbutton.SizeToFit();
            backbutton.TouchDown += (sender, e) =>
            {
                if (((TestPage5)Element)?.CustomBackButtonAction != null)
                {
                    ((TestPage5)Element)?.CustomBackButtonAction.Invoke();

                }
            };
            backbutton.Frame = new CoreGraphics.CGRect(0, 0, UIScreen.MainScreen.Bounds.Width / 4,
                NavigationController.NavigationBar.Frame.Height);
            var buttoncontainer = new UIView(new CoreGraphics.CGRect(0, 0, backbutton.Frame.Width, backbutton.Frame.Height));
            buttoncontainer.AddSubview(backbutton);
            var fixspace = new UIBarButtonItem(UIBarButtonSystemItem.FixedSpace)
            { Width = -16f };
            var backbuttonitem = new UIBarButtonItem("", UIBarButtonItemStyle.Plain, null) { CustomView = backbutton };
            NavigationController.TopViewController.NavigationItem.LeftBarButtonItems = new[] { fixspace, backbuttonitem };
        }
    }
    }

android:

在主要活動中添加以下內容:

protected override void OnCreate(Bundle savedInstanceState)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;
 
            base.OnCreate(savedInstanceState);
 
            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
            LoadApplication(new App());
 
            //important to trigger OnOptionItemSelected
            Android.Support.V7.Widget.Toolbar toolbar
             = this.FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
            SetSupportActionBar(toolbar);

也在 mainactivity.cs 中:

public override bool OnOptionsItemSelected(IMenuItem item)
        {
            // check if the current item id 
            // is equals to the back button id
            if (item.ItemId == 16908332) // xam forms nav bar back button id
            {
                // retrieve the current xamarin 
                // forms page instance
                var currentpage = (TestPage5)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);
            }
        }
 
        //android Hardware back button event
        public override void OnBackPressed()
        {
            // this is really not necessary, but in Android user has both Nav bar back button 
            // and physical back button, so its safe to cover the both events
 
            var currentpage = (BaseContentPage)Xamarin.Forms.Application.Current.
                MainPage.Navigation.NavigationStack.LastOrDefault();
 
            if (currentpage?.CustomBackButtonAction != null)
            {
                currentpage?.CustomBackButtonAction.Invoke();
            }
            else
            {
                base.OnBackPressed();
            }
        }

這是我寫的完整的博客,它處理相同的,

Android:

我在 android 中使用NavigationPage Renderer實現了這個功能

Android 實現

iOS:

我已經使用Page Renderer在 iOS 中實現了這個功能

public class CustomPageRenderer:PageRenderer
{
    public override void ViewWillAppear(bool animated)
    {
        base.ViewWillAppear(animated);
        if (Element != null && Element is BasePage basePage && basePage.BindingContext != null &&
            basePage.BindingContext is BaseViewModel baseViewModel)
        {
            SetCustomBackButton(baseViewModel);
        }
    }
    private void SetCustomBackButton(BaseViewModel baseViewModel)
    {
        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
            baseViewModel.BackPressedAction?.Invoke(false);
        };
        //var views = NavigationController?.NavigationBar.Subviews;
        NavigationController?.NavigationBar.AddSubview(btn);
    }
}

筆記:

請在基本視圖 model 中創建BackPressedAction Action 以捕獲后按事件

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM