Hi Guys,
In Xamarin Foms if want to handle hardware back press back button, you just need override function OnBackButtonPressed() of your ContentPage. If you want to handle software/hardware back button from your ViewModel, my article will show you how to.
Fist, create your customize base ContentPage
public class XFVNNavigationAnimationBasePageView : ContentPage { protected override bool OnBackButtonPressed() { var bindingContext = BindingContext as XFVNNavigationAnimationBasePageViewModel; var result = bindingContext?.OnBackButtonPressed() ?? base.OnBackButtonPressed(); return result; } public void OnSoftBackButtonPressed() { var bindingContext = BindingContext as XFVNNavigationAnimationBasePageViewModel; bindingContext?.OnSoftBackButtonPressed(); } public bool NeedOverrideSoftBackButton { get; set; } = false; }
and here is our base ViewModel
public class XFVNNavigationAnimationBasePageViewModel { /// <summary> /// //false is default value when system call back press /// </summary> /// <returns></returns> public virtual bool OnBackButtonPressed() { //false is default value when system call back press return false; } /// <summary> /// called when page need override soft back button /// </summary> public virtual void OnSoftBackButtonPressed() { } }
In project iOS, your page renderer need override LeftBarButtonItem of NavigationController.TopViewController
public class XFVNNavigationAnimationBasePageViewRenderer : PageRenderer { public override void ViewWillAppear(bool animated) { base.ViewWillAppear(animated); var page = Element as XFVNNavigationAnimationBasePageView; if (page == null) return; #region for soft back button var root = NavigationController.TopViewController; if (!page.NeedOverrideSoftBackButton) return; var title = NavigationPage.GetBackButtonTitle(Element); root.NavigationItem.SetLeftBarButtonItem( new UIBarButtonItem(title, UIBarButtonItemStyle.Plain, (sender, args) => { page.OnSoftBackButtonPressed(); }), true); #endregion } }
And in the Android project we must SetNavigationOnClickListener for our NavigationPageRenderer
public class AnimationNavigationRenderer : NavigationPageRenderer, Android.Views.View.IOnClickListener { protected override void SetupPageTransition(Android.Support.V4.App.FragmentTransaction transaction, bool isPush) { if (isPush) transaction.SetCustomAnimations(Resource.Animation.enter_from_right, Resource.Animation.exit_to_left, Resource.Animation.enter_from_left, Resource.Animation.exit_to_right); else { transaction.SetCustomAnimations(Resource.Animation.enter_from_left, Resource.Animation.exit_to_right, Resource.Animation.enter_from_right, Resource.Animation.exit_to_left); } } #region nav toolbar private static readonly FieldInfo ToolbarFieldInfo; private bool _disposed; private AToolbar _toolbar; static AnimationNavigationRenderer() { // get _toolbar private field info ToolbarFieldInfo = typeof(NavigationPageRenderer).GetField("_toolbar", BindingFlags.NonPublic | BindingFlags.Instance) ; } public void OnClick(Android.Views.View v) { // Call the NavigationPage which will trigger the default behavior // The default behavior is to navigate back if the Page derived classes return true from OnBackButtonPressed override var curPage = Element.CurrentPage as XFVNNavigationAnimationBasePageView; if (curPage == null) { Element.PopAsync(); } else { if (curPage.NeedOverrideSoftBackButton) curPage.OnSoftBackButtonPressed(); else Element.PopAsync(); } } protected override void OnLayout(bool changed, int l, int t, int r, int b) { base.OnLayout(changed, l, t, r, b); UpdateToolbarInstance(); } protected override void OnConfigurationChanged(Configuration newConfig) { base.OnConfigurationChanged(newConfig); UpdateToolbarInstance(); } protected override void Dispose(bool disposing) { if (disposing && !_disposed) { _disposed = true; RemoveToolbarInstance(); } base.Dispose(disposing); } private void UpdateToolbarInstance() { RemoveToolbarInstance(); GetToolbarInstance(); } private void GetToolbarInstance() { try { //sai o cho nay nay //how to get toolbar navigation page _toolbar = (AToolbar)ToolbarFieldInfo.GetValue(this); _toolbar.SetNavigationOnClickListener(this); } catch (Exception exception) { System.Diagnostics.Debug.WriteLine($"Can't get toolbar with error: {exception.Message}"); } } private void RemoveToolbarInstance() { if (_toolbar == null) return; _toolbar.SetNavigationOnClickListener(null); _toolbar = null; } #endregion }
Boom!
Vide demo for Android, iOS, Full source code
Happy Xamarin Codding!
Advertisements