Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Typeface in ActionBar's Tab Title

I'm trying to set a custom Typeface on my ActionBar tabs' titles.

I have seen more developers asking for a proper way to do this on SO (e.g. How to customize the font of Action Bar tabs & How (if possible) could I set a custom font in a ActionBar on tab text with a font in my assets folder?) but no answers.

So far, I've followed two approaches:

1) The first one was inspired by this SO question and consists of inflating a custom layout for each tab:

LayoutInflater inflater = LayoutInflater.from(this);
View customView = inflater.inflate(R.layout.tab_title, null); // a custom layout for the tab title, basically contains a textview...

TextView titleTV = (TextView) customView.findViewById(R.id.action_custom_title);
        titleTV.setText(mSectionsPagerAdapter.getPageTitle(i));
        titleTV.setGravity(Gravity.CENTER_VERTICAL);
        titleTV.setTypeface(((MyApp) getApplicationContext()).getCustomTypeface());

// ...Here I could also add any other styling I wanted to...

actionBar.getTabAt(i).setCustomView(customView);

This doesn't look like a very good approach because if the tabs + actions don't fit to the ActionBar in landscape mode, the tab titles are displayed in an overflow list (Spinner/Drop-down) but the selected value shows up as empty. And when you click on this list's item, then all of these views disappear. This is particularly annoying when, for example the user expands a search action view which causes android to show the tab as a Drop-down.

2) I've tried another approach as presented here which involves using a SpannableString but the font doesn't change to my custom one.

SpannableString s = new SpannableString(mSectionsPagerAdapter.getPageTitle(i));
s.setSpan(new TypefaceSpan(this, "FontName.ttf"), 0, s.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
actionBar.addTab(actionBar.newTab().setText(s).setTabListener(this));

Class TypefaceSpan can be seen here.

So...

Does anyone know a proper way of styling the ActionBar tabs' titles with a Typeface from "/assets/fonts/..."? Any help would be greatly appreciated.

EDIT:

More on the second approach. The TypefaceSpan class I'm using is actually a fork of android.text.style.TypefaceSpan as presented by user @twaddington here: How to Set a Custom Font in the ActionBar Title?

EDIT 2:

In the previous link, a comment stated: "if the textAllCaps attribute is set to true on the underlying TextView (e.g. via a theme), then the custom font won't appear. This was an issue for me when I applied this technique to the action bar tab items".

I have changed my style so that textAllCaps was set to false and now the second method seems to work. I'll test it a bit and post the results.

Conclusion:

The solution in the previous edit seems to work.

Marking @CommonsWare's answer as correct for its relevancy.

PS-EDIT for @PeteH:

I asked this 6 months ago so I don't remember all the details. I believe that for this app I ended up following a different approach for navigation. All I can find now in the app (regarding swiping...) is an Activity whose layout contains a ViewPager with a PagerTabStrip, which I styled like this:

// Style the Tab Strip:
Typeface tf = ((MyApplication) getApplication()).getTabStripTypeface(); // Used this to keep a single instance of the typeface (singleton pattern) and avoid mem. leaks
PagerTabStrip strip = (PagerTabStrip) findViewById(R.id.pager_title_strip);
strip.setTabIndicatorColor(getResources().getColor(R.color.myColor));
strip.setDrawFullUnderline(true);
for (int i = 0; i < strip.getChildCount(); ++i) {
    View nextChild = strip.getChildAt(i);
    if (nextChild instanceof TextView) {
        TextView textViewToConvert = (TextView) nextChild;
                    textViewToConvert.setAllCaps(false); 
        textViewToConvert.setTypeface(tf);
    }
}

This is not the same as the issue presented in this question, though.

The only related code I can find is this, where I set a SpannableString:

// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
    SpannableString s = new SpannableString(mSectionsPagerAdapter.getPageTitle(i));
    s.setSpan(new TypefaceSpan(this, "FontName.ttf"), 0, s.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    actionBar.addTab(actionBar.newTab().setText(s).setTabListener(this));
}

...whereas in my styles.xml, I had the style for the Actionbar's Tab Text like this:

<!-- action bar tabtext style -->
<style name="ActionBarTabText.MyApplication" parent="@android:style/Widget.Holo.ActionBar.TabText">
    <item name="android:textAppearance">@android:style/TextAppearance.Holo.Medium</item>
    <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
    <item name="android:textSize">15sp</item>
    <item name="android:textStyle">bold</item>
    <item name="android:textAllCaps">false</item>
    <item name="android:ellipsize">marquee</item>
    <item name="android:maxLines">1</item>
</style>
like image 757
user1987392 Avatar asked Oct 02 '22 09:10

user1987392


1 Answers

TypefaceSpan will only work with the three built-in typefaces.

That being said, forking TypefaceSpan to use one where the Typeface is loaded from a local file path should not be that hard. Rather than treating the String in the constructor as being a face family name, you would treat it as an local file path, adjusting apply() to load it from there. Typeface itself is not Parcelable, so you would need to work with the path.

The problem with getting the Typeface from assets is that the TypefaceSpan would need access to an AssetManager, and it would not readily have access to one after being put into and rebuilt from a Parcel.

I have not used your first technique, but I am not surprised that you are having problems.

You might also consider dropping action bar tabs entirely and switching to a ViewPager with a tabbed indicator, as you may have an easier time styling, say, Jake Wharton's TabPageIndicator.

like image 142
CommonsWare Avatar answered Oct 08 '22 04:10

CommonsWare