• Xamarin.Forms 在Prism 下实现导航栏回退按钮点击事件截留的正确姿势


    1.定义一个用于实现菜单管理的容器基类 MenuContainerPage 继承自 ContentPage, IMenuContainerPage

     1 public class MenuContainerPage : ContentPage, IMenuContainerPage
     2 {
     3 
     4         SlideMenuView slideMenu;
     5         public SlideMenuView SlideMenu
     6         {
     7             get
     8             {
     9                 return slideMenu;
    10             }
    11             set
    12             {
    13                 if (slideMenu != null)
    14                     slideMenu.Parent = null;
    15                 slideMenu = value;
    16                 if (slideMenu != null)
    17                     slideMenu.Parent = this;
    18             }
    19         }
    20 
    21         public Action ShowMenuAction { get; set; }
    22 
    23         public Action HideMenuAction { get; set; }
    24 
    25         public void ShowMenu ()
    26         {
    27             if (SlideMenu.IsShown)
    28             {
    29                 HideMenuAction?.Invoke();
    30             }
    31             else
    32             {
    33                 ShowMenuAction?.Invoke();
    34             }
    35         }
    36 
    37         public void HideMenu ()
    38         {
    39             HideMenuAction?.Invoke();
    40         }
    41 
    42 
    43         public virtual void OnSoftBackButtonPressed()
    44         {
    45         }
    46         public virtual bool NeedOverrideSoftBackButton { get; set; } = false;
    47     }

    2. 定义一个泛型视图基类BaseContentPage<T> 继承自  MenuContainerPage  其中T派生自 ViewModelBase,该类用于模型绑定上下文, 申明 

    OnSoftBackButtonPressed 和 NeedOverrideSoftBackButton 用来接受点击事件和开关
     1     public abstract class BaseContentPage<T> : MenuContainerPage where T : ViewModelBase
     2     {
     3         public T ViewModel => (T)this.BindingContext;
     4         public BaseContentPage()
     5         {
     6             Padding = 0;
     7             this.SlideMenu = new RightSideMasterPage();
     8             BackgroundColor = Color.White;
     9             DeviceDisplay.KeepScreenOn = true;
    10         }
    11         protected override void OnAppearing()
    12         {
    13             base.OnAppearing();
    14         }
    15         protected override void OnDisappearing()
    16         {
    17             base.OnDisappearing();
    18         }
    19 
    20 
    21         public override void OnSoftBackButtonPressed()
    22         {
    23             var bindingContext = BindingContext as ViewModelBaseCutom;
    24             bindingContext?.OnSoftBackButtonPressed();
    25         }
    26         public override bool NeedOverrideSoftBackButton { get; set; } = false;
    27 
    28     }

    3. 要实现导航栏回退按钮侦听事件,需要自定义 NavigationPageRenderer ,这里我们定义一个 CustomNavigationPageRenderer 实现 Android.Views.View.IOnClickListener 接口

      1  public class CustomNavigationPageRenderer : NavigationPageRenderer, Android.Views.View.IOnClickListener
      2     {
      3 
      4         private static readonly FieldInfo ToolbarFieldInfo;
      5         private bool _disposed;
      6         private Toolbar _toolbar;
      7         static CustomNavigationPageRenderer()
      8         {
      9             ToolbarFieldInfo = typeof(NavigationPageRenderer).GetField("_toolbar", BindingFlags.NonPublic | BindingFlags.Instance);
     10         }
     11         public CustomNavigationPageRenderer(Context context) : base(context) { }
     12 
     13         public override void OnViewAdded(Android.Views.View child)
     14         {
     15             base.OnViewAdded(child);
     16 
     17             if (child.GetType() == typeof(Toolbar))
     18             {
     19                 _toolbar = (Toolbar)child;
     20                 _toolbar.ChildViewAdded += Toolbar_ChildViewAdded;
     21             }
     22         }
     23 
     24         private void Toolbar_ChildViewAdded(object sender, ChildViewAddedEventArgs e)
     25         {
     26             var view = e.Child.GetType();
     27             if (view == typeof(AppCompatTextView))
     28             {
     29                 var textView = (AppCompatTextView)e.Child;
     30                 textView.TextSize = 14;
     31                 textView.SetTypeface(null, TypefaceStyle.Bold);
     32                 textView.RequestLayout();
     33                 if (_toolbar != null)
     34                 {
     35                     _toolbar.ChildViewAdded -= Toolbar_ChildViewAdded;
     36                 }
     37             }
     38         }
     39 
     40         public new void OnClick(Android.Views.View v)
     41         {
     42             if (!(Element.CurrentPage is MenuContainerPage curPage))
     43             {
     44                 Element.PopAsync();
     45             }
     46             else
     47             {
     48                 if (curPage.NeedOverrideSoftBackButton)
     49                     curPage.OnSoftBackButtonPressed();
     50 
     51                 else Element.PopAsync();
     52             }
     53         }
     54 
     55         protected override void OnLayout(bool changed, int l, int t, int r, int b)
     56         {
     57             base.OnLayout(changed, l, t, r, b);
     58             UpdateToolbarInstance();
     59         }
     60 
     61         protected override void OnConfigurationChanged(Configuration newConfig)
     62         {
     63             base.OnConfigurationChanged(newConfig);
     64             UpdateToolbarInstance();
     65         }
     66 
     67         protected override void Dispose(bool disposing)
     68         {
     69             if (disposing && !_disposed)
     70             {
     71                 _disposed = true;
     72                 RemoveToolbarInstance();
     73             }
     74 
     75             base.Dispose(disposing);
     76         }
     77 
     78         private void UpdateToolbarInstance()
     79         {
     80             RemoveToolbarInstance();
     81             GetToolbarInstance();
     82         }
     83 
     84         private void GetToolbarInstance()
     85         {
     86             try
     87             {
     88                 _toolbar = (Toolbar)ToolbarFieldInfo.GetValue(this);
     89                 _toolbar.SetNavigationOnClickListener(this);
     90             }
     91             catch (Exception exception)
     92             {
     93                 System.Diagnostics.Debug.WriteLine($"Can't get toolbar with error: {exception.Message}");
     94             }
     95         }
     96 
     97         private void RemoveToolbarInstance()
     98         {
     99             if (_toolbar == null) return;
    100 
    101             _toolbar.ChildViewAdded -= Toolbar_ChildViewAdded;
    102             _toolbar.SetNavigationOnClickListener(null);
    103             _toolbar = null;
    104         }
    105 
    106     }

     其中重写 OnClick(Android.Views.View v)

     1  public new void OnClick(Android.Views.View v)
     2 {
     3             if (!(Element.CurrentPage is MenuContainerPage curPage))
     4             {
     5                 Element.PopAsync();
     6             }
     7             else
     8             {
     9                 if (curPage.NeedOverrideSoftBackButton)
    10                     curPage.OnSoftBackButtonPressed();
    11 
    12                 else Element.PopAsync();
    13             }
    14         }

    4. 定义测试页面 SaleOrderBillPage 继承  BaseContentPage<SaleOrderBillPageViewModel>  其中 SaleOrderBillPageViewModel 表示视图模型,在OnAppearing 中 开启当前页面是否启用回退截留

     NeedOverrideSoftBackButton = true;

     1 protected override void OnAppearing()
     2         {
     3             base.OnAppearing();
     4             if (Content == null)
     5             {
     6                 try
     7                 {
     8                     InitializeComponent();
     9 
    10                     ToolbarItems.Clear();
    11                     NeedOverrideSoftBackButton = true;
    12 
    13                     string btnIco = "uf0c7";
    14                     foreach (var toolBarItem in this.GetToolBarItems(ViewModel, true, btnIco).ToList())
    15                     {
    16                         ToolbarItems.Add(toolBarItem);
    17                     }
    18                 }
    19                 catch (Exception ex) { Log.Write(ex); }
    20                 return;
    21             }
    22         }


    5.  在ViewModelBase 中重写 OnSoftBackButtonPressed

    1    public async virtual void OnSoftBackButtonPressed()
    2         {
    3             var ok = await _dialogService.ShowConfirmAsync("你是否要保存单据?", "提示", "确定", "取消");
    4             if (!ok)
    5             {
    6                 await _navigationService.GoBackAsync();
    7             }
    8         }

    当点击返回按钮时,提示表单是否要存储,效果如下:

    protected override void OnAppearing()        {            base.OnAppearing();            if (Content == null)            {                try                {                    InitializeComponent();
                        ToolbarItems.Clear();                    NeedOverrideSoftBackButton = true;
                        string btnIco = "uf0c7";                    foreach (var toolBarItem in this.GetToolBarItems(ViewModel, true, btnIco).ToList())                    {                        ToolbarItems.Add(toolBarItem);                    }                }                catch (Exception ex) { Log.Write(ex); }                return;            }        }
  • 相关阅读:
    4.8 C++ typeid操作符
    4.7 C++ dynamic_cast操作符
    tomcat中class和jar的加载顺序(转)
    java Files类和Paths类的用法 (转)
    搭建DUBBO项目解决DUBBO.XML标签报错的问题(转载)
    Maven异常:Could not find artifact
    在docker宿主机上查找指定容器内运行的所有进程的PID
    jmap、jstack、jps无法连接jvm解决办法
    linux中如何查看某一进程的启动时间
    Eureka与ZooKeeper 的比较(转)
  • 原文地址:https://www.cnblogs.com/mschen/p/13926136.html
Copyright © 2020-2023  润新知