Dynamically add logo to Navigation bar from image stored within internal memory - Xamarin Forms app

JurgenJurgen Member ✭✭
edited September 2018 in Xamarin.Forms

I have a scenario where the logo of a client should be featured in the navigation header. This naturally requires the image to be downloaded and saved into internal memory of the phone and then fed dynamically to the nav bar. I will try to explain how the app layout is configured as well as give a small outline of what I have attempted until now.

I am using a MasterDetail page called RootPage,xaml.
MenuPage.xaml for a side menu with a Stacklayout and BoxViews representing the various buttons.
A Tabbed Main page MainPage.xaml loading 2 content pages from C#.

In the App.xaml.cs, this is how the above are configured:

var menuPage = new MenuPage(UserSettings);
NavigationPage = new NavigationPage(new MainPage(def, "", UserSettings));
RootPage = new RootPage(UserSettings);
RootPage.Master = menuPage;
RootPage.Detail = NavigationPage;
MainPage = RootPage;

I have managed to show static logos in both iOS and Android.

In the case of iOS, the logo is specified in MenuPage.xaml.cs within the Shared Project, as below:

`this.Icon = "xlogo_small.png";

In the case of Android, I did not find a way do it from the Shared project.
This simply does not work:

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

Instead I had to use the Toolbar.axml within the Xamarin.Android project.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar 
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:popupTheme="@style/ThemeOverlay.AppCompat.Light">

<RelativeLayout android:layout_width="wrap_content"
        android:layout_height="fill_parent">

<ImageView
android:id="@+id/logo"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:scaleType="fitCenter"
        android:src="@drawable/xlogo_small" 
        android:layout_gravity="right"
        android:layout_alignParentRight="true" />
</RelativeLayout>
</android.support.v7.widget.Toolbar>

Essentially I need a way to dynamically display the logo which would be residing within the device's internal memory in both the Android & iOS cases. Preferably, I would prefer a method that does not require the use of the native Toolbar.axml, but if there'd be a way to inject the logo (from internal memory) into the Toolbar.axml, I guess that would work too!

Answers

  • LandLuLandLu Member, Xamarin Team Xamurai

    You can try to use custom renderer to achieve that on Android platform:

    [assembly: ExportRenderer(typeof(NavigationPage), typeof(CustomPageRenderer))]
    namespace Demo.Droid
    {
        public class CustomPageRenderer : NavigationPageRenderer
        {
            public CustomPageRenderer(Context context) : base(context)
            {
    
            }
    
            protected override void OnElementChanged(ElementChangedEventArgs<NavigationPage> e)
            {
                base.OnElementChanged(e);
    
                // Change this class name to yours.
                var page = Element.CurrentPage as MainPage;
                if (page != null)
                {
                    if (page.Icon == "logo.png")
                    {
                        var bar = (Android.Support.V7.Widget.Toolbar)typeof(NavigationPageRenderer)
                            .GetField("_toolbar", BindingFlags.NonPublic | BindingFlags.Instance)
                            .GetValue(this);
                        bar.SetLogo(Resource.Drawable.logo);
                    }
                    else...// Set other images
                }      
            }
        }
    }
    

    Make sure this logo.png is in your android project's drawable folder. Also do not forget to set the Icon property in the forms's content page.

  • JurgenJurgen Member ✭✭

    @LandLu thanks for your answer. As stated in the first part of my question, the issue is that the logo image would be downloaded via a web service call during run time, and can not therefore, be bundled within the drawables (Android) or resources (iOS) folder prior to installing the app. I will however look into your solution, to see whether I can modify it in a way that works with the internal memory. If you have any ideas, kindly let me know! Thanks again :smile:

Sign In or Register to comment.