0
votes

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?

2

2 Answers

2
votes

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" />
2
votes

You can do it by using messaging center and define what you want to do. Let say you want on your MainPage to set an icon and the rest to remove it.You can use something like:

On not main page:

MessagingCenter.Send<Page, string>(this, "toolbar", "notmain");

On main page:

MessagingCenter.Send<Page, string>(this, "toolbar", "main");

You subscribe for those message in your MainActivity like below.

var toolbarIcon = FindViewById<ImageView>(Resource.Id.navbar_adp_logo);

                //recommendation: do not use lambda, define a delegate function
                MessagingCenter.Subscribe<Page, string>(this, "toolbar", (page, toolbar) =>
                {
                    if (toolbar == "main")
                    {
                        toolbarIcon.Visibility = ViewStates.Visible;
                    }
                    else
                    {
                        toolbarIcon.Visibility = ViewStates.Gone;
                    }

                });

Don't forget to define in xaml

 android:id="@+id/navbar_adp_logo"

If you want it only on one page then instead of sending messages from each page you can do the follow once on the page required

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

            MessagingCenter.Send<Page, string>(this, "toolbar", "notmain");
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            MessagingCenter.Send<Page, string>(this, "toolbar", "main");
        }