Mahajan344
Mahajan344

Reputation: 2550

Change hamburger icon in master detail navigation xamarin forms

I am working on Xamarin forms where I need to show master detail navigation after successful login screen. I want to change default hamburger icon but not able to change it.

Please see below code I am using.

Since my app have login screen so I don't want to show any navigation on Login screen. I am just setting main page in app.xaml.cs

public App()
{
    InitializeComponent();

    MainPage = new Login();
}

Now after login clicked I tried following approach to change icon but didn't work

var dashboard = new Dashboard(){Icon = "Menuicon.png" };
Application.Current.MainPage = dashboard;

Dashbaord is masterdetail page and on its ctor, I am setting detail page like below

Detail = new NavigationPage((Page)Activator.CreateInstance(typeof(DashbaordDetail))) { Icon = "Menuicon.png" };

Its not reflecting new icon

Upvotes: 6

Views: 8966

Answers (3)

Christian Regli
Christian Regli

Reputation: 2246

The accepted answer does not work, as it shows the hamburger icon also when there should be a back icon. Ronak Shetiyas answer above does work.

Code adapted for AndroidX AppCompat

public class NavigationPageRenderer : Xamarin.Forms.Platform.Android.AppCompat.MasterDetailPageRenderer
{
    protected AndroidX.AppCompat.Widget.Toolbar TitleToolBar;

    protected override void OnLayout(bool changed, int l, int t, int r, int b)
    {
        base.OnLayout(changed, l, t, r, b);
        TitleToolBar  = FindViewById<AndroidX.AppCompat.Widget.Toolbar>(Resource.Id.toolbar);
        // change the default hamburger / back icon
        if (TitleToolBar != null)
        {
            for (var i = 0; i < TitleToolBar.ChildCount; i++)
            {
                var imageButton = TitleToolBar.GetChildAt(i) as AndroidX.AppCompat.Widget.AppCompatImageButton;
                
                var drawerArrow = imageButton?.Drawable as DrawerArrowDrawable;
                if (drawerArrow == null)
                    continue;
                var displayBack = false;
                if (Xamarin.Forms.Application.Current.MainPage is MasterDetailPage masterDetailPage)
                {
                    var detailPage = masterDetailPage.Detail;
                    var navPageLevel = detailPage.Navigation.NavigationStack.Count;
                    if (navPageLevel > 1)
                        displayBack = true;
                    imageButton.SetImageResource(displayBack
                        ? Resource.Drawable.ic_arrow_back
                        : Resource.Drawable.ic_menu);
                }
            }
        }
    }
}

Upvotes: 0

Ronak Shetiya
Ronak Shetiya

Reputation: 980

i applied this tweak and it helped me. now i can see back button also after navigation

protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
    base.OnLayout(changed, l, t, r, b);
    var toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
    if (toolbar != null)
    {
        for (var i = 0; i < toolbar.ChildCount; i++)
        {
            var imageButton = toolbar.GetChildAt(i) as ImageButton;
            var drawerArrow = imageButton?.Drawable as DrawerArrowDrawable;
            if (drawerArrow == null)
                continue;
            bool displayBack = false;
            var app = Xamarin.Forms.Application.Current;
            var detailPage = (app.MainPage as MasterDetailPage).Detail;
            var navPageLevel = detailPage.Navigation.NavigationStack.Count;
            if (navPageLevel > 1)
                displayBack = true;
            if (!displayBack)
                ChangeIcon(imageButton, Resource.Drawable.iconMenu2);
            if (displayBack)
                ChangeIcon(imageButton, Resource.Drawable.back1);
        }
    }
}
private void ChangeIcon(ImageButton imageButton, int id)
{
    if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop)
        imageButton.SetImageDrawable(Context.GetDrawable(id));
    imageButton.SetImageResource(id);
}

Upvotes: 6

Wilson Vargas
Wilson Vargas

Reputation: 2899

You should use a custom renderer.

In your Android project, like this:

[assembly: ExportRenderer(typeof(CustomIcon.Views.MainPage), typeof(IconNavigationPageRenderer))]
namespace CustomIcon.Droid
{
    public class IconNavigationPageRenderer : MasterDetailPageRenderer
    {
        private static Android.Support.V7.Widget.Toolbar GetToolbar() => (CrossCurrentActivity.Current?.Activity as MainActivity)?.FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);

        protected override void OnLayout(bool changed, int l, int t, int r, int b)
        {
            base.OnLayout(changed, l, t, r, b);
            var toolbar = GetToolbar();
            if (toolbar != null)
            {
                for (var i = 0; i < toolbar.ChildCount; i++)
                {
                    var imageButton = toolbar.GetChildAt(i) as ImageButton;

                    var drawerArrow = imageButton?.Drawable as DrawerArrowDrawable; 
                    if (drawerArrow == null)
                        continue;

                    imageButton.SetImageDrawable(Forms.Context.GetDrawable(Resource.Drawable.newIcon));
                }
            }
        }
    }
}

In your iOS project only use the same icon from you xaml file in your PCL project, like this:

<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage  xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:local="clr-namespace:CustomIcon.Views;assembly=CustomIcon"
         Title="MainPage"
         Icon="newIcon.png"
         x:Class="CustomIcon.Views.MainPage">
<MasterDetailPage.Master>
    <local:MasterPage x:Name="masterPage" />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
    <NavigationPage>
        <x:Arguments>
            <local:Page1 />
        </x:Arguments>
    </NavigationPage>
</MasterDetailPage.Detail>

For more information see my repo on github: https://github.com/wilsonvargas/CustomIconNavigationPage

Upvotes: 7

Related Questions