Install and How to use

How to handle Hardware/Software back button from ViewModel in Xamarin Forms

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 AndroidiOSFull source code

Happy Xamarin Codding!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s