Toolbar title refresh problem on Android

zeb94zeb94 ITMember ✭✭

I have found a way to change the application's toolbar title following this example on GitHub.
The problem I'm facing though is that on some Android devices the title font and location is not immediately updated but I have to go to another page (which displays the title correctly) and come back to the page with the problem to finally see an updated title font and position. This happens only on some Android devices when the app is launched, and in those devices this problems always happens.

Following you can find how I changed the title font and position and then examples of what happens:

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        ...
    }

    static Class ActionMenuViewClass = null;
    static Constructor ActionMenuViewConstructor = null;

    static Typeface typeface = null;
    public static Typeface Typeface
    {
        get
        {
            if (typeface == null)
                typeface = Typeface.CreateFromAsset(Android.App.Application.Context.ApplicationContext.Assets, "Abel-Regular.ttf");

            return typeface;
        }
    }

    public override View OnCreateView(string name, Context context, IAttributeSet attrs)
    {
        if (name.Equals("android.support.v7.widget.Toolbar", StringComparison.InvariantCultureIgnoreCase))
        {
            var customLoginIfNeeded = CreateCustomToolbar(name, context, attrs);
            if (customLoginIfNeeded != null)
                return customLoginIfNeeded;
        }

        return base.OnCreateView(name, context, attrs);
    }

    public override View OnCreateView(View parent, string name, Context context, IAttributeSet attrs)
    {
        if (name.Equals("android.support.v7.widget.Toolbar", StringComparison.InvariantCultureIgnoreCase))
        {
            var customLoginIfNeeded = CreateCustomToolbar(name, context, attrs);
            if (customLoginIfNeeded != null)
                return customLoginIfNeeded;
        }

        return base.OnCreateView(parent, name, context, attrs);
    }

    View CreateCustomToolbar(string name, Context context, IAttributeSet attrs)
    {
        // android.support.v7.widget.Toolbar
        View view = null;

        try
        {
            if (ActionMenuViewClass == null)
                ActionMenuViewClass = ClassLoader.LoadClass(name);
        }
        catch (ClassNotFoundException ex)
        {
            return null;
        }

        if (ActionMenuViewClass == null)
            return null;

        if (ActionMenuViewConstructor == null)
        {
            try
            {
                ActionMenuViewConstructor = ActionMenuViewClass.GetConstructor(new Class[] {
                    Class.FromType(typeof(Context)), Class.FromType(typeof(IAttributeSet))
                });
            }
            catch (SecurityException)
            {
                return null;
            }
            catch (NoSuchMethodException)
            {
                return null;
            }
        }

        if (ActionMenuViewConstructor == null)
            return null;

        try
        {
            Java.Lang.Object[] args = new Java.Lang.Object[] { context, (Java.Lang.Object)attrs };
            view = (View)(ActionMenuViewConstructor.NewInstance(args));
        }
        catch (IllegalArgumentException)
        {
            return null;
        }
        catch (InstantiationException)
        {
            return null;
        }
        catch (IllegalAccessException)
        {
            return null;
        }
        catch (InvocationTargetException)
        {
            return null;
        }

        if (null == view)
            return null;

        View v = view;

        new Handler().Post(() =>
        {
            try
            {
                if(v is ViewGroup vg)
                {
                    for (int i = 0; i < vg.ChildCount; i++)
                    {
                        var child = vg.GetChildAt(i);
                        var button = child as Button;
                        var textView = child as TextView;

                        if (button != null)
                        {
                            var title = button.Text;

                            if (!string.IsNullOrEmpty(title))
                            {
                                button.SetTypeface(Typeface, TypefaceStyle.Normal);
                            }
                        }
                        else if(textView != null)
                        {
                            Android.Support.V7.Widget.Toolbar.LayoutParams lp = new Android.Support.V7.Widget.Toolbar.LayoutParams((int)GravityFlags.Center)
                            {
                                Height = -2
                            };
                            textView.LayoutParameters = lp;
                            textView.SetTypeface(Typeface, TypefaceStyle.Normal);

                            // Attempts to force the update
                            textView.PostInvalidate();
                            textView.ForceLayout();
                            v.PostInvalidate();
                            v.ForceLayout();
                        }
                    }
                }
                else if (v is LinearLayout)
                {
                    var ll = (LinearLayout)v;
                    for (int i = 0; i < ll.ChildCount; i++)
                    {
                        var button = ll.GetChildAt(i) as Button;

                        if (button != null)
                        {
                            var title = button.Text;

                            if (!string.IsNullOrEmpty(title))
                            {
                                button.SetTypeface(Typeface, TypefaceStyle.Normal);
                            }
                        }
                    }
                }
                else if (v is TextView)
                {
                    var tv = (TextView)v;
                    string title = tv.Text;

                    if (!string.IsNullOrEmpty(title))
                    {
                        tv.SetTypeface(Typeface, TypefaceStyle.Normal);
                    }
                }
            }
            catch (ClassCastException)
            {
            }
        });

        return view;
    }
}

First page (the one with the problem) at first load:

Second page (here the toolbar title is right):

First page again after coming back from the second page (now this is correct too):

Answers

  • jezhjezh Member, Xamarin Team Xamurai

    Could you please provide us the device model and the android version of the devices?
    And could you please share a basic demo that can reproduce the problem through online repo ?

  • zeb94zeb94 ITMember ✭✭

    At the moment I found a workaround setting the title directly from the Toolbar.axml since I don't need a different title for each page.
    @jezh right now I'm on a strict deadline so I don't have time to setup an online repo to reproduce the problem so I'll use the workaround I found for now. As soon as I'm out of this deadline I'll provide che repo.

Sign In or Register to comment.