Search code examples
androidxamarin.formsandroid-imageviewandroid-toolbarnavigationbar

Xamarin.Forms: how to assign an icon to the Navigation Bar to a single page on Android


I try to use an icon instead of the title on the main page of my Xamarin.Forms app.

I've read a lot of related topics, but I didn't found any solution:

On iOS this is done easily by adding this on my first page:

NavigationPage.SetTitleIcon(this, "navbar_logo.png");

On Android, I've added this on Toolbar.axml:

<ImageView android:src="@drawable/navbar_adp_logo" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_gravity="center" />

This works, but the icon is now visible on each page on Android...

I've tried to use a renderer to hide the icon when I navigate to another page. For this I would like to use the override OnViewAdded() method:

public class CustomNavigationPageRenderer : NavigationPageRenderer 
{   
    public override void OnViewAdded(Android.Views.View child)   
    {  ...   } 
}

I try to use OnViewAdded() cause I've seen in QuickWatch that this method is called each time that I navigate in my Xamarin.Forms app.

I've also noticed that the method is called 2 times during navigation:

  • the first time, the child parameter is a V7.Widget.Toolbar:

V7.Widget.Toolbar

  • the second time, the child parameter is a Xamarin.Forms.Platform.Android.PageContainer:

PageContainer

So I tried to cast the child into Xamarin.Forms.Platform.Android.PageContainer, but I can't do it because this object is "internal":

PageContainer is inaccessible due to its protection method.

Why couldn't I do it in code, if I can do it with QuickWatch? I don't see if there is another way to achieve this... Would you have any suggestion?


Solution

  • You should override the OnElementChanged method and look for changes to the CurrentPage property. That way you'll always know when a specific page is shown and can hide or show the toolbar icon.

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);
    
        if (e.PropertyName.Equals("CurrentPage"))
            // If we're on MainPage show the icon, otherwise hide it
            ChangeToolbarIconVisibility(Element.CurrentPage is MainPage); 
    }
    
    private void ChangeToolbarIconVisibility(bool visible) 
    {
        var toolbarIcon = FindViewById<ImageView>(Resource.Id.toolbarIcon);        
        toolbarIcon.Visibility = visible ? Android.Views.ViewStates.Visible : Android.Views.ViewStates.Gone;            
    }
    

    To make this work, remember to add the id to your modified Toolbar layout:

    <ImageView android:src="@drawable/navbar_adp_logo" 
               android:layout_width="wrap_content" 
               android:layout_height="wrap_content" 
               android:layout_gravity="center"
               android:id="@+id/toolbarIcon" />