6

Is there an easy way to make all textviews (and any other text elements in my app) to use a custom font of my own (and not the built-in choices), without having to manually set them via textview.setTypeface()?

I guess extending Textview would do the trick but then building interfaces with the visual editor is kind of a pain. I was thinking of something like styling but can't find how to set a custom font there.

MichelReap
  • 5,630
  • 11
  • 37
  • 99
  • Check this please http://stackoverflow.com/questions/6926263/add-custom-font-for-complete-android-application and http://stackoverflow.com/questions/9327053/using-custom-font-in-android-textview-using-xml – Lia Pronina Aug 21 '13 at 11:14
  • Hi @MichelReap can you please mark my answer as accepted, if its solved your problem... – Paras Valera Nov 21 '16 at 05:04

5 Answers5

14

If you need to set one font for all TextViews in android application you can use this solution. It will override ALL TextView's typefaces, includes action bar and other standard components, but EditText's password font won't be overriden.

MyApp.java

    public class MyApp extends Application {

    @Override
    public void onCreate()
    {
                TypefaceUtil.overrideFont(getApplicationContext(), "SERIF", "fonts/Roboto-Regular.ttf"); 
     }
    }

TypefaceUtil.java

public class TypefaceUtil {

    /**
     * Using reflection to override default typeface
     * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE OVERRIDDEN
     * @param context to work with assets
     * @param defaultFontNameToOverride for example "monospace"
     * @param customFontFileNameInAssets file name of the font from assets
     */
    public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) {
        try {
            final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);

            final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
            defaultFontTypefaceField.setAccessible(true);
            defaultFontTypefaceField.set(null, customFontTypeface);
        } catch (Exception e) {
            Log.e("TypefaceUtil","Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride);
        }
    }
}

themes.xml

     <?xml version="1.0" encoding="utf-8"?>
   <resources>
     <style name="MyAppTheme" parent="@android:style/Theme.Holo.Light">
    <!-- you should set typeface which you want to override with TypefaceUtil -->
    <item name="android:typeface">serif</item>
   </style>
   </resources>

Update for Android 5.0 or greater

As i have investigated and tested on device running api 5.0 or greater this solution is working fine because i am using the single style.xml file and not making other style.xml in values-21 folder

Although Some users asking me that this solution not working with android 5.0 device (they may be using values-21 style.xml i guess)

So that is because Under API 21, most of the text styles include fontFamily setting, like

<item name="fontFamily">@string/font_family_body_1_material</item>

Which applys the default Roboto Regular font:

<string name="font_family_body_1_material">sans-serif</string>

So the best solution is

If Any one having problem not working for 5.0+. Don't override typeface in your values-v21 styles.

Just override font in values/style.xml and you will good to go :)

Paras Valera
  • 602
  • 4
  • 13
  • 1
    Works great on a lot of devices. But I'm trying on some devices such as a Samsung S5 (5.0.1) and it's not working. – Eurig Jones Oct 27 '15 at 12:34
  • @Lena we are using @style/Theme.AppCompat.Light.NoActionBar with this not working – Prags Oct 19 '16 at 05:54
  • what is the outcome you're receiving? – Lena Bru Oct 19 '16 at 06:12
  • 2
    Is this the source? [github gist by artem-zinnatullin](https://gist.github.com/artem-zinnatullin/7749076) - if yes then you should give credits, if no then you should ask for credits on this gist. – Talha Oct 24 '16 at 05:17
  • Have implemented the above mentioned approach in my app. It is working for most of the languages. But in 4.4.4 Samsung device burmese fonts are not loaded properly. Please suggest. App image screenshot here -> https://ibb.co/gvzOXv – Vinay Kashyap T S Jul 05 '17 at 09:09
  • @user3752389 Glade to here its helps you and other developers, you can upvote the answer by the way ;), Regarding your issue with 4.4.4 device we need to have more details about your problem to rectify it. – Paras Valera Jul 05 '17 at 10:18
1

You can create a method to set typeface for a textview in a common class and you can set the call that method and send the textview as its attribute.

Hariharan
  • 24,741
  • 6
  • 50
  • 54
0

Yes. Just make a style and set it to a certain font and then set the entire app in that style.

superuser
  • 731
  • 10
  • 28
0

You can do it by creating subclass of TextView and call setTypeFace method within it. For example in constructor.

Peter Moskala
  • 360
  • 1
  • 9
0

Make a method in Constants class so that it can be accessed from all fragments and activities:

 public static void overrideFonts(final Context context, final View v) {
    try {
        if (v instanceof ViewGroup) {
            ViewGroup vg = (ViewGroup) v;
            for (int i = 0; i < vg.getChildCount(); i++) {
                View child = vg.getChildAt(i);
                overrideFonts(context, child);
            }
        } else if (v instanceof TextView) {
            ((TextView) v).setTypeface(Typeface.createFromAsset(context.getAssets(), "font/Lato-Regular.ttf"));
        } else if (v instanceof EditText) {
            ((EditText) v).setTypeface(Typeface.createFromAsset(context.getAssets(), "font/Lato-Regular.ttf"));
        } else if (v instanceof Button) {
            ((Button) v).setTypeface(Typeface.createFromAsset(context.getAssets(), "font/Lato-Regular.ttf"));
        }
    } catch (Exception e) {
    }
}

Call Method in activity as:

 Constants.overrideFonts(MainActivity.this, getWindow().getDecorView().getRootView());

Call method in Fragment as:

  Constants.overrideFonts(getActivity(), view);
Pratibha Sarode
  • 1,819
  • 17
  • 17