Change hamburger icon in master detail navigation xamarin forms
Asked Answered
I

3

6

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

Islet answered 14/11, 2017 at 13:2 Comment(0)
M
7

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

Mcswain answered 15/11, 2017 at 0:40 Comment(8)
Hi @Wilson Vargas, I've studied your sample but I have a question. I've added a second page to simulate navigation. On this second page, the "back" icon is replaced by the "newIcon" that is used as Hamburger icon for open the Master pane of the MasterDetail page. Is there a way to keep the "back" icon when it's not the main level of the MasterDetail page that is displayed? Thank you!Bystander
@Bystander same issue, mine was I remove the burger icon, this also results removing the back buttonDariusdarjeeling
Am I the only one who doesn't find CrossCurrentActivity?Misadventure
@AhmedSalah you need to install the package "CurrentActivityPlugin"Isar
@WilsonVargas GetToolbar() returns null whenever I siwtch from my loginh page(which isn't wrapped in NavigationPage) to MainePage.Isar
Why this answer is marked? This is not the proper answer. I tried to run same and getting same issue with back button.Incommunicable
it's not working a bit, as toolbar is always returned as null it doesn't change the icon, even your git repository isn't working wellFirm
The solution @Gold.strike: #47287097Khoisan
T
6

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);
}
Threw answered 12/12, 2018 at 5:21 Comment(2)
Can you help with iOS renderer as well?Firm
@Blu I would suggest creating a custom layout on your base page and hide your navigation bar and use that custom layout in all your content pagesThrew
V
0

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);
                }
            }
        }
    }
}
Verbify answered 29/3 at 10:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.