How to change navigation page back button in xamarin forms

前端 未结 2 2023
醉话见心
醉话见心 2020-12-17 06:54

I am trying to change back arrow image in navigation page. For this in android app i created navigation page renderer and then using method toolbar.SetNavigationIcon and its

相关标签:
2条回答
  • 2020-12-17 06:54

    I solved this the next way: In my MainActivity i am added static toolbar property and identified it in OnCreateOptionsMenu

        public static Toolbar ToolBar { get; private set; }
    
        public override bool OnCreateOptionsMenu(IMenu menu)
        {
            ToolBar = FindViewById<Toolbar>(Resource.Id.toolbar);
            ToolBar.SetNavigationIcon(Resource.Drawable.arrow);
            return base.OnCreateOptionsMenu(menu);
        }
    
        protected override void OnCreate(Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;
            ....
        }
    

    Then in PageRenderer:

    protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
    {
         base.OnElementChanged(e);
         MainActivity.ToolBar?.SetNavigationIcon(Resource.Drawable.arrow);
    }
    

    But!! From 2 ways i have bad effect with redrawing

    Usage:

    async void tapImage_Tapped(object sender, EventArgs e)
    {
         await Navigation.PushAsync(new ChooseGenrePage(_listGenres));
    }
    
    0 讨论(0)
  • 2020-12-17 07:06

    If your MainActivity is FormsApplicationActivity, you could refer to this example :

    https://github.com/jessejiang0214/ChangeBackIconInXF/tree/master/Droid

    If your MainActivity type is FormsAppCompatActivity, you could custom a PageRenderer and change the Toolbar's NavigationIcon.

    For example :

    [assembly: ExportRenderer(typeof(ContentPage), typeof(NavigationPageRendererDroid))]
    ...
    public class NavigationPageRendererDroid : PageRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
        {
            base.OnElementChanged(e);
    
            var context = (Activity)Xamarin.Forms.Forms.Context;
            var toolbar = context.FindViewById<Android.Support.V7.Widget.Toolbar>(Droid.Resource.Id.toolbar);
    
            toolbar.NavigationIcon = Android.Support.V4.Content.ContextCompat.GetDrawable(context, Resource.Drawable.Back);
        }
    }
    

    Usage :

    MainPage = new NavigationPage(new MainPage());
    ...
    //When click a button in MainPage, navigate to another page
    private async void Button_Clicked(object sender, EventArgs e)
    {
        await Navigation.PushAsync(new TestPage());
    }
    

    Effect.


    Update :

    When you use Navigation.PushAsync() method navigate to another page, the system will automatically update the Toolbar's icon, you could find in the source code :

    protected virtual Task<bool> OnPushAsync(Page view, bool animated)
    {
        return SwitchContentAsync(view, animated);
    }
    
    Task<bool> SwitchContentAsync(Page page, bool animated, bool removed = false, bool popToRoot = false)
    {
        ...
        UpdateToolbar();
        ...
    }
    
    void UpdateToolbar()
    {
        ...
        bool isNavigated = ((INavigationPageController)Element).StackDepth > 1;
        if (isNavigated)
        {
            ...
            if (NavigationPage.GetHasBackButton(Element.CurrentPage))
            {
                 //Set the navigation back  icon < =================== !!! =-=
                 var icon = new DrawerArrowDrawable(activity.SupportActionBar.ThemedContext);
                 icon.Progress = 1;
                 bar.NavigationIcon = icon;
            }
        }
        ...
    }
    

    Solution :

    So we have no choice but to custom a NavigationPageRenderer, override the OnPushAsync method to set the Toolbar's icon.

    using AToolbar = Android.Support.V7.Widget.Toolbar;
    [assembly: ExportRenderer(typeof(CustomNavigationPage), typeof(NavigationPageRendererDroid))] // APPCOMP
    ...
    public class NavigationPageRendererDroid : Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer // APPCOMP
    {
        public AToolbar toolbar;
        public Activity context;
    
        protected override Task<bool> OnPushAsync(Page view, bool animated)
        {
            var retVal = base.OnPushAsync(view, animated);
    
            context = (Activity)Xamarin.Forms.Forms.Context;
            toolbar = context.FindViewById<Android.Support.V7.Widget.Toolbar>(Droid.Resource.Id.toolbar);
    
            if (toolbar != null)
            {
                if (toolbar.NavigationIcon != null)
                {
                    toolbar.NavigationIcon = Android.Support.V4.Content.ContextCompat.GetDrawable(context, Resource.Drawable.Back);
                    //toolbar.SetNavigationIcon(Resource.Drawable.Back);
                }
            }
            return retVal;
        }
    }
    

    The CustomNavigationPage are defined in PCL :

    public class CustomNavigationPage : NavigationPage
    {
        public CustomNavigationPage(Page startupPage) : base(startupPage)
        {
        }
    }
    

    Usage :

    public App()
    {
        InitializeComponent();
    
        MainPage = new CustomNavigationPage(new MainPage());
    }
    ...
    // In MainPage
    private async void Button_Clicked(object sender, EventArgs e)
    {
        await Navigation.PushAsync(new TestPage());
    }
    
    0 讨论(0)
提交回复
热议问题