How to set default font family for entire Android app
Asked Answered
V

16

346

I'm using the Roboto light font in my app. To set the font I've to add the android:fontFamily="sans-serif-light" to every view. Is there any way to declare the Roboto font as default font family to entire app? I've tried like this but it didn't seem to work.

<style name="AppBaseTheme" parent="android:Theme.Light"></style>

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:fontFamily">sans-serif-light</item>
</style>
Vellavelleity answered 6/5, 2013 at 18:24 Comment(2)
This might help you: https://mcmap.net/q/56656/-is-it-possible-to-set-a-custom-font-for-entire-of-applicationChamorro
You can now specify custom fonts right from the XML in android studio 3.0 developer.android.com/guide/topics/ui/look-and-feel/…Cravens
V
326

The answer is yes.

Global Roboto light for TextView and Button classes:

<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:textViewStyle">@style/RobotoTextViewStyle</item>
    <item name="android:buttonStyle">@style/RobotoButtonStyle</item>
</style>

<style name="RobotoTextViewStyle" parent="android:Widget.TextView">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

<style name="RobotoButtonStyle" parent="android:Widget.Holo.Button">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

Just select the style you want from list themes.xml, then create your custom style based on the original one. At the end, apply the style as the theme of the application.

<application
    android:theme="@style/AppTheme" >
</application>

It will work only with built-in fonts like Roboto, but that was the question. For custom fonts (loaded from assets for example) this method will not work.

EDIT 08/13/15

If you're using AppCompat themes, remember to remove android: prefix. For example:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:textViewStyle">@style/RobotoTextViewStyle</item>
    <item name="buttonStyle">@style/RobotoButtonStyle</item>
</style>

Note the buttonStyle doesn't contain android: prefix, but textViewStyle must contain it.

Vellavelleity answered 6/5, 2013 at 20:55 Comment(11)
Where did you get the sans-serif-light value from? Is there a list of valid values for fontFamily somewhere? I've been looking through the docs, as well as the theme and style files in the Android source and can't find anything.Misbelief
From this answer: #12128831 EDIT: But now I see you have posted same comment there ;)Vellavelleity
this is possible only for API level 16.. the name "android:fontFamily" exists only in level 16 or above.. is there a way to do that also for API 14 for example?Irresoluble
@LorenzoBarbagli, you can check CalligraphyPhilomena
Hi tomrozb, do you need to add a style-element for each widget-type?Nobby
@Nobby Yes, you have to change style of each UI element type (eg. TextView, Button) to apply a custom fontVellavelleity
Well what do I do if I have a custom font?Ninetta
Is there any way to change font family for all elements (views)?Creative
yes,, I also want to add custom font to the entire app. How can i do that ?. Do i need to override TextView and replace all the TextView as suggested in first answerCabot
TextViewStyle is only available for Android 11+, and that is wayyyyyy too limiting to be used. Ref: developer.android.com/reference/androidx/autofill/inline/common/…Athamas
It does not work with Canvas and OpenGL ViewsBritteny
S
209

With the release of Android Oreo you can use the support library to reach this goal.

  1. Check in your app build.gradle if you have the support library >= 26.0.0
  2. Add "font" folder to your resources folder and add your fonts there
  3. Reference your default font family in your app main style:

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
       <item name="android:fontFamily">@font/your_font</item>
       <item name="fontFamily">@font/your_font</item> <!-- target android sdk versions < 26 and > 14 if theme other than AppCompat -->
    </style>
    

Check https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html for more detailed information.

Sideway answered 31/8, 2017 at 10:8 Comment(10)
When targeting API 26+, this should be the accepted method. When using Support Library, just remove the android: prefixSatan
@Satan on this particular case it has backwards compatibility since I'm using Theme.AppCompat so there's no need to add the unprefixed versionAnalyst
if you use the unprefixed version only, it's ok. The prefixed one just will be ignored on API <26Satan
This doesn't set the font everywhere... e.g. if you have styles that derive from Base.TextAppearance.AppCompat, it's not used there.Esophagus
@Ixx, how to override those styles too?Erkan
do you know how to change it programmatically?Insanity
Remember to also use AppCompatTextView when targeting api<26Predate
if you do this, then it appears that you can't change fontFamily in a textAppearance. So be careful with it.Flosser
What about built-in fonts? In my case, I'd like to use them instead of adding duplicates or another ones. Those methods only take more space...Cannady
fontFamily (without android prefix) overrides all TextViews so hard, you cannot even override it with attributes or styles. Tested on 8.1.0. Using only android:fontFamily works as expected on 8.1.0.Athamas
G
66

To change your app font follow the following steps:

  1. Inside res directory create a new directory and name it font.
  2. Insert your font .ttf/.otf inside the font folder, Make sure the font name is lower case letters and underscore only.
  3. Inside res -> values -> styles.xml inside <resources> -> <style> add your font <item name="android:fontFamily">@font/font_name</item>.

enter image description here

Now all your app text should be in the font that you add.

Grissom answered 14/2, 2019 at 17:57 Comment(3)
while using custom fonts how can I add bold font along with regular fonts?Hesketh
That works with only API level 26 and above, what about API 21 and below?Menstruum
Great answer, very useful and to the point, for those who are importing an otf custom font.Neall
N
34

READ UPDATES BELOW

I had the same issue with embedding a new font and finally got it to work with extending the TextView and set the typefont inside.

public class YourTextView extends TextView {

    public YourTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public YourTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public YourTextView(Context context) {
        super(context);
        init();
    }

    private void init() {
        Typeface tf = Typeface.createFromAsset(context.getAssets(),
            "fonts/helveticaneue.ttf");
        setTypeface(tf);
    }
}

You have to change the TextView Elements later to from to in every element. And if you use the UI-Creator in Eclipse, sometimes he doesn't show the TextViews right. Was the only thing which work for me...

UPDATE

Nowadays I'm using reflection to change typefaces in whole application without extending TextViews. Check out this SO post

UPDATE 2

Starting with API Level 26 and available in 'support library' you can use

android:fontFamily="@font/embeddedfont"

Further information: Fonts in XML

Nitrometer answered 6/5, 2013 at 20:14 Comment(9)
This is not the solution. I'm using many different views, not only the TextView. I want to set the font once and forget about it. In addition, your code creates new object for every TextView. At least declare the field as static to load the font from assets once.Vellavelleity
...well, there's a find and replace function, which works really well in this caseNitrometer
This isn't going to work. You cannot call getContext() when the variable is static. You should implement it in singleton like way, otherwise the current code won't even compile.Vellavelleity
i reverted the last commit.Nitrometer
@Vellavelleity :D i just realized, that the last fast changes i did, were because of your comments! as you have enough points, you are welcome to optimize the code example yourself. otherwise we will still talk about the topic in a few years, when nobody cares about smartphones anymore ;)Nitrometer
I just suggested to optimize the code (keep the typeface as static field, so it's not loaded from assets for every single custom view). I'm not using this answer because there are better options to load fonts globally. I'm not going to optimize it, because IMO it's the worst solution to apply custom font to a view.Vellavelleity
IMO this was the only way which worked in API 14. but i understand your static point, so thanks for your comment, but it s a won't fix ;)Nitrometer
how can we revert back to default. I am doing something like this: pastebin.com/qJqbEBqEHughhughes
The question is about changing all the views in app to particular font rather than customizing all views.Douceur
Y
15

Add this line of code in your res/value/styles.xml

<item name="android:fontFamily">@font/circular_medium</item>

the entire style will look like that

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:fontFamily">@font/circular_medium</item>
</style>

change "circular_medium" to your own font name..

Yarber answered 24/10, 2019 at 13:21 Comment(2)
I tried this and it's working fine but I am wondering why people use the calligraphy library instead?Sweptwing
@Sweptwing calligraphy is a pretty old library that's not even maintained anymore. generally people use it because they have used it for ages. when calligraphy was released, the solution described in this answer was not possible, because font resources were only introduced in 2017Monroe
N
8

It's very very very easy to do in Android Studio.

  1. In this method you need to verify your minsdkveriosn. It must need minsdkversion >=16

Ex:

  1. Create "font" folder inside "res" folder. In android studio New > Folder > Font Folder.

See image:

  1. Upload your font file to that font folder.

Ex:

  1. In you style.xml file, Under style in "Base application theme" add this line.

    <item name="android:fontFamily">@font/ubuntubold</item>

Ex:

Natation answered 30/5, 2021 at 2:48 Comment(2)
Looks like it only works for AppCompat activities but not Leanback (not available for AndroidTV).Kemme
Only for API >= 26. Also has wrong image in step 3.Stockist
G
7

Not talk about performance, for custom font you can have a recursive method loop through all the views and set typeface if it's a TextView:

public class Font {
    public static void setAllTextView(ViewGroup parent) {
        for (int i = parent.getChildCount() - 1; i >= 0; i--) {
            final View child = parent.getChildAt(i);
            if (child instanceof ViewGroup) {
                setAllTextView((ViewGroup) child);
            } else if (child instanceof TextView) {
                ((TextView) child).setTypeface(getFont());
            }
        }
    }

    public static Typeface getFont() {
        return Typeface.createFromAsset(YourApplicationContext.getInstance().getAssets(), "fonts/whateverfont.ttf");
    }
}

In all your activity, pass current ViewGroup to it after setContentView and it's done:

ViewGroup group = (ViewGroup) getWindow().getDecorView().findViewById(android.R.id.content);
Font.setAllTextView(group);

For fragment you can do something similar.

Graceless answered 25/4, 2016 at 10:19 Comment(3)
Sounds great but wondering how to make it work in recyclerView contents?Triggerhappy
I just tried this. too heavy to render. Slowing down recyclerView like hell.Triggerhappy
Totally not recommended for any list view, this trick is just for save time to code static view.Graceless
T
5

Another way to do this for the whole app is using reflection based on this answer

public class TypefaceUtil {
    /**
     * Using reflection to override default typefaces
     * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE
     * OVERRIDDEN
     *
     * @param typefaces map of fonts to replace
     */
    public static void overrideFonts(Map<String, Typeface> typefaces) {
        try {
            final Field field = Typeface.class.getDeclaredField("sSystemFontMap");
            field.setAccessible(true);
            Map<String, Typeface> oldFonts = (Map<String, Typeface>) field.get(null);
            if (oldFonts != null) {
                oldFonts.putAll(typefaces);
            } else {
                oldFonts = typefaces;
            }
            field.set(null, oldFonts);
            field.setAccessible(false);
        } catch (Exception e) {
            Log.e("TypefaceUtil", "Can not set custom fonts");
        }
    }

    public static Typeface getTypeface(int fontType, Context context) {
        // here you can load the Typeface from asset or use default ones
        switch (fontType) {
            case BOLD:
                return Typeface.create(SANS_SERIF, Typeface.BOLD);
            case ITALIC:
                return Typeface.create(SANS_SERIF, Typeface.ITALIC);
            case BOLD_ITALIC:
                return Typeface.create(SANS_SERIF, Typeface.BOLD_ITALIC);
            case LIGHT:
                return Typeface.create(SANS_SERIF_LIGHT, Typeface.NORMAL);
            case CONDENSED:
                return Typeface.create(SANS_SERIF_CONDENSED, Typeface.NORMAL);
            case THIN:
                return Typeface.create(SANS_SERIF_MEDIUM, Typeface.NORMAL);
            case MEDIUM:
                return Typeface.create(SANS_SERIF_THIN, Typeface.NORMAL);
            case REGULAR:
            default:
                return Typeface.create(SANS_SERIF, Typeface.NORMAL);
        }
    }
}

then whenever you want to override the fonts you can just call the method and give it a map of typefaces as follows:

Typeface regular = TypefaceUtil.getTypeface(REGULAR, context);
Typeface light = TypefaceUtil.getTypeface(REGULAR, context);
Typeface condensed = TypefaceUtil.getTypeface(CONDENSED, context);
Typeface thin = TypefaceUtil.getTypeface(THIN, context);
Typeface medium = TypefaceUtil.getTypeface(MEDIUM, context);
Map<String, Typeface> fonts = new HashMap<>();
fonts.put("sans-serif", regular);
fonts.put("sans-serif-light", light);
fonts.put("sans-serif-condensed", condensed);
fonts.put("sans-serif-thin", thin);
fonts.put("sans-serif-medium", medium);
TypefaceUtil.overrideFonts(fonts);

for full example check

This only works for Android SDK 21 and above for earlier versions check the full example

Tisiphone answered 20/10, 2015 at 12:0 Comment(0)
E
4

Just use this lib compile it in your grade file

complie'me.anwarshahriar:calligrapher:1.0'

and use it in the onCreate method in the main activity

Calligrapher calligrapher = new Calligrapher(this);
calligrapher.setFont(this, "yourCustomFontHere.ttf", true);

This is the most elegant super fast way to do that.

Epiphora answered 24/8, 2017 at 3:15 Comment(0)
O
2

This is work for my project, source https://gist.github.com/artem-zinnatullin/7749076

Create fonts directory inside Asset Folder and then copy your custom font to fonts directory, example I am using trebuchet.ttf;

Create a class TypefaceUtil.java;

import android.content.Context;
import android.graphics.Typeface;
import android.util.Log;

import java.lang.reflect.Field;
public class TypefaceUtil {

    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) {

        }
    }
}

Edit theme in styles.xml add below

<item name="android:typeface">serif</item>

Example in My styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:typeface">serif</item><!-- Add here -->
    </style>


    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowFullscreen">true</item>
    </style>
</resources>

Finally, in Activity or Fragment onCreate call TypefaceUtil.java

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TypefaceUtil.overrideFont(getContext(), "SERIF", "fonts/trebuchet.ttf");
    }
Ola answered 12/2, 2019 at 4:46 Comment(0)
A
1

Android does not provide much in the way of support for applying fonts across the whole app (see this issue). You have 4 options to set the font for the entire app:

  • Option1: Apply reflection to change the system font
  • Option2: Create and subclass custom View classes for each View that needs a custom font
  • Option3: Implement a View Crawler which traverses the view hierarchy for the current screen
  • Option4: Use a 3rd party library.

Details of these options can be found here.

Aleuromancy answered 24/3, 2016 at 17:26 Comment(0)
D
0

I know this question is quite old, but I have found a nice solution. Basically, you pass a container layout to this function, and it will apply the font to all supported views, and recursively cicle in child layouts:

public static void setFont(ViewGroup layout)
{
    final int childcount = layout.getChildCount();
    for (int i = 0; i < childcount; i++)
    {
        // Get the view
        View v = layout.getChildAt(i);

        // Apply the font to a possible TextView
        try {
            ((TextView) v).setTypeface(MY_CUSTOM_FONT);
            continue;
        }
        catch (Exception e) { }

        // Apply the font to a possible EditText
        try {
            ((TextView) v).setTypeface(MY_CUSTOM_FONT);
            continue;
        }
        catch (Exception e) { }

        // Recursively cicle into a possible child layout
        try {
            ViewGroup vg = (ViewGroup) v;
            Utility.setFont(vg);
            continue;
        }
        catch (Exception e) { }
    }
}
Delight answered 8/10, 2016 at 13:15 Comment(0)
M
0

to merely set typeface of app to normal, sans, serif or monospace(not to a custom font!), you can do this.

define a theme and set the android:typeface attribute to the typeface you want to use in styles.xml:

<resources>

    <!-- custom normal activity theme -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <!-- other elements -->
        <item name="android:typeface">monospace</item>
    </style>

</resources>

apply the theme to the whole app in the AndroidManifest.xml file:

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application
        android:theme="@style/AppTheme" >
    </application>
</manifest>

android reference

Maritime answered 3/11, 2016 at 6:57 Comment(4)
You sure that works? According to Android doc: "Must be one of the following constant values: normal, sans, serif, monospace".Vellavelleity
Oh I see...you're right...i didn't understand the question after all :x I just wanted to have my whole app to use a monospace font (not custom) and I saw it working so I posted this here.........i think my answer could still be useful for others who want to do something similar....so I'll edit it and leave it here.....i am ok is it accumulates down votes. thanks for pointing that outMaritime
Hey @Dave Cruise, does it only work for monospace? I have only tested it for monospace...and nothing else....so I'm not sure...but according to the documentation, it should work for "normal", "sans" and "serif" too...i think typeface is more general than font, so we cant use it to set font of app to a specific font like "consolas" or something.Maritime
@Maritime yea. i have no idea too. monospace work like a charm but no luck for normal, sans or serif.Brunt
H
-1

Try this library, its lightweight and easy to implement

https://github.com/sunnag7/FontStyler

<com.sunnag.fontstyler.FontStylerView
              android:textStyle="bold"
              android:text="@string/about_us"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:paddingTop="8dp"
              app:fontName="Lato-Bold"
              android:textSize="18sp"
              android:id="@+id/textView64" />
Hereunder answered 29/5, 2017 at 13:3 Comment(0)
G
-1

This is how we do it:

private static void OverrideDefaultFont(string defaultFontNameToOverride, string customFontFileNameInAssets, AssetManager assets)
{
    //Load custom Font from File                
    Typeface customFontTypeface = Typeface.CreateFromAsset(assets, customFontFileNameInAssets);

    //Get Fontface.Default Field by reflection
    Class typeFaceClass = Class.ForName("android.graphics.Typeface");
    Field defaultFontTypefaceField = typeFaceClass.GetField(defaultFontNameToOverride);

    defaultFontTypefaceField.Accessible = true;
    defaultFontTypefaceField.Set(null, customFontTypeface);
}
Gibberish answered 23/9, 2020 at 6:50 Comment(3)
Could you explain how your answer is different to the other 14 answers, and how it works?Must
what language is this? it does not look like Java, with lowercase string and upper case methods like Class.ForNameMonroe
Oh it is C# as this project is using Xamarin.Gibberish
B
-8

The answer is no, you can't. See Is it possible to set a custom font for entire of application? for more information.

There are workarounds, but nothing in the lines of "one single line of code here and all my fonts will be this instead of that".

(I kind of thank Google -and Apple- for that). Custom fonts have a place, but making them easy to replace app wide, would have created an entire world of Comic Sans applications)

Beutler answered 6/5, 2013 at 20:21 Comment(3)
Completely disagree with your commentary. Setting a font globally should be trivial to do, not something that requires the kinds of workarounds needed. It's up to the developers/designers of the world to avoid the "Comic Sans" applications, not Google/Apple to enforce that.Steddman
Consistency > Fancy design.Beutler
However, consistence < functionality. We develop apps that display biblical Hebrew. All of the stock fonts found on Android devices (including the latest Android L fonts) do an abysmal job of rendering cantillation marks (and they do a mediocre job on vowel marks, for that matter, although they are getting better). We absolutely need to use a custom font throughout our app, and we've had to write way too much code simply to get all the requisite views using it.Fluorinate

© 2022 - 2024 — McMap. All rights reserved.