0

After updating Android Support Libary v7 AppCompat I'm not able to change style to the title and the following is not wotking anymore:

int myTitleId = Resources.GetIdentifier("action_bar_title", "id", "android");
TextView barTitle = FindViewById<TextView>(myTitleId);
barTitle.SetTypeface(FontFactory.GetMyFont(this), TypefaceStyle.Normal);
tolgap
  • 9,629
  • 10
  • 51
  • 65
Daniele D.
  • 2,624
  • 3
  • 36
  • 42

2 Answers2

0

That's because AppCompat now uses a ToolBar widget as replacement for ActionBar. ToolBar creates a TextView instance for the title on-the-fly; if you dig into the (android.support.v7.widget.)ToolBar code, you'll find something like this:

mTitleTextView = new TextView(context);

(Refer to line 607 of android.support.v7.widget.ToolBar in appcompat-v7-23.0.1-sources.jar)

More importantly, no id is ever assigned to the view. This can also easily be seen by inspecting the view hierarchy:

enter image description here

That TextView that you see is the one that holds the title. The id is a generated value and not predefined (like i.e. the one for the ActionBarContainer), which means you can no longer look it up through some sort of static reference.

That explains why your code, which does an id-lookup-by-name, no longer works: the action_bar_title id is simply no longer being used here.

There are several solutions to make setting a custom font to the ActionBar title work again. The cleanest is probably to leverage the fact that setTitle() takes a CharSequence, which means you can attach a custom typeface span to it that enables the custom font and/or style to work. Doing this is some sort of a 'base' Activity would probably make most sense.

You can of course also iterate over the local view hierarchy, starting at ToolBar, but I'd say that's not quite as robust and prone to suffer from future changes (like your current code ;)).

Alternatively, consider using a library to simplify dealing with applying custom fonts. Calligraphy is usually my first stop for this.

Community
  • 1
  • 1
MH.
  • 45,303
  • 10
  • 103
  • 116
0

After integrating the new Toolbar this is how I changed style.

inside protected override void OnCreate(Bundle bundle) of my Activity (that now extends AppCompatActivity) where before there was the previous code now I have:

toolbar = FindViewById<Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);

var f = toolbar.Class.GetDeclaredField("mTitleTextView");
f.Accessible = true;
var barTitle  = (TextView)f.Get(toolbar);
barTitle.SetTypeface(FontFactory.GetMyFont(this), TypefaceStyle.Normal);

I needed also to add this on the top:

using Java.Lang; //for the reflection
using Toolbar =  Android.Support.V7.Widget.Toolbar; 

and in the layout.axml I included the toolbar.axml in this way:

//...
<include
android:id="@+id/toolbar"
layout="@layout/toolbar" /> 
//...
Daniele D.
  • 2,624
  • 3
  • 36
  • 42
  • FWIW: this approach is just a wonky as your original one. While things may work for now, it's guaranteed to break as soon as the Android team decides to rename the `mTitleTextView` field, move it to some sort of delegate, or remove it altogether. You *shouldn't* be relying on the framework's internal implementation details, especially in production code. I would strongly recommend a more robust approach if you don't want to run into the same issue again a few updates down the road. – MH. Oct 19 '15 at 10:31