Home > Net >  How do I register an arrow click handler in the navigation page?
How do I register an arrow click handler in the navigation page?

Time:06-06

I have two navigation pages, one root page, and a second page that can be accessed from the first. I have no desire to prescribe a separate button for this when there is an arrow at the top. Is it possible to somehow register a Clicked event handler for it yourself?

CodePudding user response:

From what you are asking, I believe you are trying to have an event handler that can intercept navigation events.

Xamarin.Forms Shell has a Navigating event you can subscribe to that allows you to see the current navigation, where it intends to navigate to, and allows you to cancel navigation or redirect. This captures all navigation, so it isn't just the back button, but will also capture moving forward as well.

Here is an example of navigation being intercepted in a ContentPage:

 public class ExampleContentPage : ContentPage
    {
        public ExampleContentPage()
        {
            Content = new StackLayout
            {
                Children = {
                    new Label { Text = "Welcome to Xamarin.Forms!" }
                }
            };
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();

            // subscribe to event listener on appearing
            Shell.Current.Navigating  = Current_Navigating;
        }

        protected override void OnDisappearing()
        {
            base.OnDisappearing();

            // remove event listener on disappearing
            Shell.Current.Navigating -= Current_Navigating;
        }

        private async void Current_Navigating(object sender, ShellNavigatingEventArgs e)
        {
            if (sender is Shell shell)
            {

                // cancels navigation so we can do what we need
                if (e.CanCancel)
                {
                    e.Cancel();
                }



                // continue navigation to it's original target if we so choose
                Shell.Current.Navigating -= Current_Navigating;
                await Shell.Current.GoToAsync(e.Target, true);
            }
        }
    }

However; if you're looking to override the functionality of the arrow button, I think you need to define the Shell's BackButtonBehavior.

This can be done either through XAML or C#. I've attached Microsoft's examples here:

<ContentPage ...>    
    <Shell.BackButtonBehavior>
        <BackButtonBehavior Command="{Binding BackCommand}"
                            IconOverride="back.png" />   
    </Shell.BackButtonBehavior>
    ...
</ContentPage>
Shell.SetBackButtonBehavior(this, new BackButtonBehavior
{
    Command = new Command(() =>
    {
        ...
    }),
    IconOverride = "back.png"
});

And here is the documentation for overriding the back button behavior: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/navigation#back-button-behavior

CodePudding user response:

To handle the backbutton event on android, you can override the OnOptionsItemSelected and OnBackPressed method in mainactivity, like:

public override void OnBackPressed()
        {
            // this is not necessary, but in Android user 
            // has both Nav bar back button and
            // physical back button its safe 
            // to cover the both events

            // retrieve the current xamarin forms page instance
            var currentpage = (BackArrowTest)
            Xamarin.Forms.Application.
            Current.MainPage.Navigation.
            NavigationStack.LastOrDefault();

            // check if the page has subscribed to 
            // the custom back button event
            if (currentpage?.CustomBackButtonAction != null)
            {
                currentpage?.CustomBackButtonAction.Invoke();
            }
            else
            {
                base.OnBackPressed();
            }
        }
        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 = (BackArrowTest)
                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);
            }
        }

Then you can create a page which has EnableBackButtonOverrideProperty and your custom event like:

public class BackArrowTest : ContentPage
    {
        public Action CustomBackButtonAction { get; set; }
        public static readonly BindableProperty EnableBackButtonOverrideProperty =
               BindableProperty.Create(
               nameof(EnableBackButtonOverride),
               typeof(bool),
               typeof(BackArrowTest),
               false);
        public bool EnableBackButtonOverride
        {
            get
            {
                return (bool)GetValue(EnableBackButtonOverrideProperty);
            }
            set
            {
                SetValue(EnableBackButtonOverrideProperty, value);
            }
        }}

At last you can set the event:

<bk:BackArrowTest  xmlns:bk="clr-namespace:MyForms2"
                   xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
EnableBackButtonOverride="True"
 x:Class="MyForms2.MyPage1"
  >
    
        <StackLayout>
            <Label Text="Welcome to Xamarin.Forms!"
                VerticalOptions="CenterAndExpand" 
                HorizontalOptions="CenterAndExpand" />
        </StackLayout>
   
</bk:BackArrowTest>

codebehind:

public partial class MyPage1 : BackArrowTest
    {
        public MyPage1()
        {
         
            InitializeComponent();
            this.EnableBackButtonOverride = true;
            this.CustomBackButtonAction = () => { Console.WriteLine("Do something"); };
        }
    }

FYI:don't forget to set the Actionbarsupport in mainactivity like:

  AndroidX.AppCompat.Widget.Toolbar toolbar = this.FindViewById<AndroidX.AppCompat.Widget.Toolbar>(Resource.Id.toolbar);
            SetSupportActionBar(toolbar);
  • Related