Search code examples
androidxamarinxamarin.androidandroid-toolbar

Toolbar Image update when rotating


I have a Xamarin Forms App where I set the Toolbar through an xml file.

<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/customToolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="?android:attr/actionBarSize"
android:background="?android:attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

<ImageView
android:id="@+id/toolbarImage" 
android:layout_width="100dp"
android:layout_height="match_parent"
android:layout_gravity="right"
android:layout_weight="1"
android:paddingRight="5dp"/>
</android.support.v7.widget.Toolbar>

And set it in the OnCreate method of the MainActivity with

ToolbarResource = Resource.Layout.CustomToolbar;

The ImageView doesn't have a source attribute because the image itself is received as base64 string from the server. To add the picture to the Toolbar I used the OnStart method

ImageView toolbarImg = this.FindViewById<ImageView>(Resource.Id.toolbarImage);
            if(!String.IsNullOrEmpty(imgAsBase64))
            {
                    byte[] imageBytes = Convert.FromBase64String(imgAsBase64);
                    Android.Graphics.Bitmap decodedByte = Android.Graphics.BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
                    toolbarImg.SetImageBitmap(decodedByte);

            }

So far this is working, but when I changed the orientation the image disappeared.

What I have tried was to add the Image in OnConfigurationChanged again but that didn't changed anything.

Also setting the Image of the ImageView to null before assigning the new picture, Invalidate(), PostInvalidate(), RequestLayout() also didn't help. Still when I change the orientation no Image is shown.

Would appreciate some help on this. Thanks in advance


Solution

  • Two solutions:

    1) Remove |ConfigChanges.Orientation from ConfigurationChanges = ConfigChanges.ScreenSize|ConfigChanges.Orientation, that mean your activity will recreate when your screen rotate.

    2) Add below code in your OnConfigurationChanged method, above the SetImageToToolbar(); method, like this:

        public override void OnConfigurationChanged(Configuration newConfig)
        {
            base.OnConfigurationChanged(newConfig);
            ToolbarResource = Resource.Layout.CustomToolbar;
            global::Xamarin.Forms.Forms.Init(this, null);
            LoadApplication(new App());
            SetImageToToolbar();
        }
    

    Why should you add these code?

    I think there is something wrong in the imgView in your code when screen rotating, so I think the codes in OnCreate() method will help it.

    Update:

    There is something wrong in the second solution, if you have many pages, it will go wrong, so I provide another solution, use custom NavigationPageRenderer:

    1) Add MyNavigationPage in your pcl:

    namespace ToolbarTestApp
    {
        class MyNavigationPage:NavigationPage
        {
            public MyNavigationPage(Page root) : base(root) {
            }
        }
    }
    

    2) Replace MainPage = new MyNavigationPage(new TestPage()); with MainPage = new NavigationPage(new TestPage());

    3)Add MyNavigationPageRender in your android project:

    [assembly: ExportRenderer(typeof(MyNavigationPage), typeof(MyNavigationPageRender))]
    namespace ToolbarTestApp.Droid
    {
        class MyNavigationPageRender : NavigationPageRenderer
        {
            public MyNavigationPageRender(Context context) : base(context)
            {
            }
    
            protected override void OnLayout(bool changed, int l, int t, int r, int b)
            {
                base.OnLayout(changed, l, t, r, b);
                (Xamarin.Forms.Forms.Context as MainActivity).SetImageToToolbar();
            }
        }
    }
    

    Change your SetImageToToolbar method to public, and you needn't override OnConfigurationChanged method, just remove it.