93

Is it possible to set a custom font in an Android application?

I tried what is posted here, but I don't know where my extends Application class is...

Any help?

EDIT:

I tried the following:

  • Add an assets folder and insert the font inside as seen here:

enter image description here

  • Add a new class that extends from Application

  • Call this new class from my AndroidManifest.xml.

  • I went to my style and added it.

MyApp.java:

public class MyApp extends Application {
  @Override
  public void onCreate() {
     super.onCreate();
    FontsOverride.setDefaultFont(this, "DEFAULT", "raleway_regular.ttf");
    //  This FontsOverride comes from the example I posted above
  }
  }

AndroidManifest.xml:

<application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:supportsRtl="true"
      android:name=".MyApp"
      android:theme="@style/AppTheme">
     ....

styles.xml:

 <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:fontFamily">default</item>
 </style>

But my font is still not changning... any idea?

Then the MyApp class is called. But no effect on my fonts...

EDIT2: I realized that my buttons apply the custom font after I set a custom style for my buttons. Here is my custom button style:

<style name="MyButtonStyle" parent="Widget.AppCompat.Button">
    <item name="textAllCaps">false</item>
    <item name="android:textAllCaps">false</item>
</style>

And here is how it looks now:

enter image description here

So: my button is applying the style, but not the TextView. Any idea on why my custom font is not being applied for all items in application?

P. Mohanta
  • 130
  • 2
  • 15
Sonhja
  • 8,230
  • 20
  • 73
  • 131
  • link you provided in question is really helpful for your problem. – Androider Nov 25 '15 at 18:26
  • I know, I think my solution is there... But when I create a class that extends from Application, I can't make it work as it says my class is never used... – Sonhja Nov 25 '15 at 18:27
  • checkout some more links in my answer, seems to be helpful, one more thing my first link is really better, Thanks – Androider Nov 25 '15 at 18:31

15 Answers15

90

All I did was:

1: Added "new resource directory" to the RES folder, Selected RESOURCE TYPE as "font" from the drop-down given, named the new directory "font" and saved. NEW RESOURCE DIRECTORY

2: Added my "custom_font.ttf" to the FONT folder just created.

3: Added my custom font in the application base theme in STYLES.XML

STYLES.XML

DONE.

Numanqmr
  • 1,083
  • 9
  • 14
  • 7
    You also have to create a font family. After that it worked for me. Details here: https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html – keybee Apr 25 '18 at 08:00
  • it worked for me without having to create a font family. However, I had to use Gradle version > 3 and build tools and support libs set to 27> @keybee – Numanqmr Apr 25 '18 at 10:56
  • Worked great for me, even without font family – Julian Alberto Jun 28 '18 at 20:45
  • do you know how to change it programmatically? – majov Jul 11 '18 at 15:08
  • @majov check the answer above by #Rajeesh. that should help you! – Numanqmr Jul 12 '18 at 07:45
  • @Numanqmr do you know how to do it without 3rd party library? I would like to use android fonts feature, but want to change it programmatically without implementation of multiple themes – majov Jul 12 '18 at 07:53
  • You can use Typeface but that only works for individual views i.e. text views etc. so I wouldn't recommend it. I know no other way. Do some digging and sure you'll find it. :) @majov – Numanqmr Jul 12 '18 at 08:08
  • this simple solution works like a charm! i wonder why most answers don't mention something like this? – Sadik anass Dec 29 '19 at 21:29
81

EDIT

uk.co.chrisjenx:calligraphy Lib is not more maintained for latest android version alternative is now https://github.com/InflationX/Calligraphy

dependencies {
    implementation 'io.github.inflationx:calligraphy3:3.1.1'
    implementation 'io.github.inflationx:viewpump:2.0.3'
}

Add your custom fonts to assets/

Usage

For default font

Define your default font using CalligraphyConfig, in your Application class in the #onCreate() method and pass it to the CalligraphyInterceptor that you add to your ViewPump builder.

@Override
public void onCreate() {
    super.onCreate();
    ViewPump.init(ViewPump.builder()
        .addInterceptor(new CalligraphyInterceptor(
                new CalligraphyConfig.Builder()
                    .setDefaultFontPath("fonts/Roboto-RobotoRegular.ttf")
                    .setFontAttrId(R.attr.fontPath)
                    .build()))
        .build());
    //....
}

Inject into Context: Wrap the Activity Context:

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase));
}

Custom Style

<style name="TextViewCustomFont">
    <item name="fontPath">fonts/RobotoCondensed-Regular.ttf</item>
</style>

For Theme

<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
    <item name="android:textViewStyle">@style/AppTheme.Widget.TextView</item>
</style>

<style name="AppTheme.Widget"/>

<style name="AppTheme.Widget.TextView" parent="android:Widget.Holo.Light.TextView">
    <item name="fontPath">fonts/Roboto-ThinItalic.ttf</item>
</style>

Not more maintained by Developers Below Solution


There is a great library for custom fonts in android:Calligraphy
Here is a sample how to use it.

In Gradle you need to put this line into your app's build.gradle file:

        dependencies {
            compile 'uk.co.chrisjenx:calligraphy:2.2.0'
        }

And then make a class that extends Application and write this code:

        public class App extends Application {
            @Override
            public void onCreate() {
                super.onCreate();

                CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
                                .setDefaultFontPath("your font path")
                                .setFontAttrId(R.attr.fontPath)
                                .build()
                );
            }
        } 

You should have made on assets/ a "New Directory" "fonts" (see below), so in that code "your font path" should be "fonts/SourceSansPro-Regular.ttf". (It's just "fonts..." not "/fonts.." or "assets..")

And in the activity class put this method before onCreate:

        @Override
        protected void attachBaseContext(Context newBase) {
            super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
        }

And the last thing your manifest file should look like this:

        <application
           .
           .
           .
           android:name=".App">

And it will change the whole activity to your font! it's simple and clean!

On Assets you should right-click New Directory, call it "fonts". In the finder put the .ttf font files in there.

enter image description here

Also dont forgot to add below two lines in attrs.xml,if you dont have attrs.xml file,create new file in values.xml

 <attr format="string" name="fontPath"/> 
    <item name="calligraphy_tag_id" type="id"/>
Rajesh N
  • 6,198
  • 2
  • 47
  • 58
  • I am using ttf but i am pretty much sure that .otf will also work and best location to put it in assets folder. – Rajesh N Apr 13 '17 at 04:14
  • Put this in extend Application class CalligraphyConfig.initDefault(new CalligraphyConfig.Builder() .setDefaultFontPath("fonts/GOTHAM-MEDIUM.ttf") .setFontAttrId(R.attr.fontPath) .build()); Also dont forgot to add below two lines in values.xml – Rajesh N Apr 13 '17 at 04:17
  • hi @rajesh! you should click "Edit" and add that to your great answer! you are right, it should be **.ttf** files, sorry. – Fattie Apr 13 '17 at 10:27
  • Is it possible to change the font at runtime by a user setting using Calligraphy? For e.g. a user can change the font from Roboto to Proxima at runtime. – Bob Apr 18 '17 at 09:59
  • yes but you has to reset configuration and then restart app to see changes – Rajesh N Apr 18 '17 at 10:05
  • This is still not a one shot solution. I have to remember to add `attachBaseContext(Context newBase)` for every new activity I add. I expect a solution wherein I do all necessary configuration at once, and then it shall set the font for all TextView across the application. – Pawan Sep 28 '17 at 17:51
  • 1
    You can use fragment as maximum as possible. So that number of activity will be reduced. – Rajesh N Sep 29 '17 at 03:14
  • 1
    @Pawan to do it one step - I define a simple base class where `attachBaseContext(..)` is implemented, and then all my project Activity classes (where I want that custom font) extend that base class – Gene Bo Jan 17 '18 at 03:59
  • I did not get the purpose of last two line Can use please explain – Inzimam Tariq IT Jan 17 '18 at 14:00
  • first line defines custom attribute with name fontpath and second don't about it but you get find answer here https://github.com/chrisjenx/Calligraphy – Rajesh N Jan 17 '18 at 16:08
  • my android project doesn't have values.xml by default. Do i need to create this under values directory? – Mayank Kumar Feb 08 '18 at 09:16
  • @RajeshNasit Its working fine But In versions `M+` for changing language we also have to add `attachBaseContext` method. How to tackle that. Check my Question https://stackoverflow.com/questions/48926729/how-to-use-calligraphy-with-multi-language-support-oreo – Inzimam Tariq IT Feb 23 '18 at 06:35
  • can you change lanaguge this way? https://stackoverflow.com/questions/2900023/change-app-language-programmatically-in-android or you can ask same question by creating issue at github – Rajesh N Feb 23 '18 at 06:49
  • This library is deprecated. No longer support. Using this SDK we can't set target SDK to 29 so better use the default android font API using the support package. – Dharmendra Jan 10 '20 at 07:18
52

Write a class

public class MyApp extends Application{
// Put the onCreate code as you obtained from the post link you reffered
}

now next thing is in AndroidManifest.xml for the application tag give name for your application class. In this case it is MyApp

<application
android:name=".MyApp"
...
>
...
</application>

So whenever the App is opened , onCreate method of MyApp class would be invoked , and the font would be set.

Update Put font file under assets/fonts/your_font_file.ttf

Put this line under onCreate method of your application class(MyApp)

TypefaceUtil.overrideFont(getApplicationContext(), "SERIF", "fonts/your_font_file.ttf");

Source File for TypefaceUtil

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

        final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Map<String, Typeface> newMap = new HashMap<String, Typeface>();
            newMap.put("serif", customFontTypeface);
            try {
                final Field staticField = Typeface.class
                        .getDeclaredField("sSystemFontMap");
                staticField.setAccessible(true);
                staticField.set(null, newMap);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        } else {
            try {
                final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
                defaultFontTypefaceField.setAccessible(true);
                defaultFontTypefaceField.set(null, customFontTypeface);
            } catch (Exception e) {
                Log.e(TypefaceUtil.class.getSimpleName(), "Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride);
            }
        }
    }
}

Now update your style.xml file

put the below line your style which is included for your activity in manifest file

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

Hope this helps

Nitin Mesta
  • 1,504
  • 19
  • 32
  • Please let me know your Android OS version on which you are testing. I have observed in lollipop we need to make certain more tweeks – Nitin Mesta Nov 26 '15 at 02:50
  • Please check the following link for the solution for Lollipop and previous Android versions: (https://stackoverflow.com/a/36206275/2268466) – blueware Jul 05 '17 at 12:59
  • it change all app font in toast message,alert dialog, i don't want to user custom font in this – Adil Jan 25 '18 at 11:59
  • 2
    I have a doubt, Many manufacturers allow the user to change fonts system-wide from settings, Do that change also overrides to our font-type we set programmatically? – Bhuro Feb 04 '19 at 18:10
  • What About set Multiple Fonts ? – Gaurav Mandlik Dec 25 '20 at 09:19
  • @GauravMandlik that can't be done this way. You will need to set it separately for every view – Sambhav Khandelwal May 12 '22 at 03:30
21

Android provides simpler and best solutions which is supported over API level 14 by Support Library 26+. Fonts in XML It also supports font family option. Required import : implementation "com.android.support:support-compat:<26+ version>"

Follow these simple steps and font family will be applied in your app without any hurdle:

  1. Create a font directory inside res
  2. Paste your fonts file inside font
  3. Right-click the font folder and go to New > Font resource file. The New Resource File window appears.
  4. Add following attributes
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android">
    <font
        android:fontStyle="normal"
        android:fontWeight="400"
        android:font="@font/lobster_regular" />
    <font
        android:fontStyle="italic"
        android:fontWeight="400"
        android:font="@font/lobster_italic" />
</font-family>
  1. In above xml file. Use app only to use support library. Otherwise you can use android if your app targets API level 26+.
  2. Now go to your styles.xml and put below line in your main style.
    <item name="android:fontFamily">@font/opensans</item>
    
  3. Important : Use AppCompatActivity only if you are using support library.
  4. Or use below to set typeface programmatically

    view.setTypeface(ResourcesCompat.getFont(context, R.font.opensans));
    
Kuldeep Sakhiya
  • 3,172
  • 1
  • 18
  • 17
15

You can do it with the android SDK now, as the Android Developer official youtube channel published in set/2017 here.

Requires API Level 23 and above.

You just need to put your font file in the res/font folder and reference them in your TextView in case you need a specific one with the android:fontFamily attribute.

If you want a base font on your whole app, simply put

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

in your styles.xml

You can download a custom font from Android Studio and on the go if you want as well. All of this you can find with details on the video above.

Francisco Nin
  • 196
  • 1
  • 13
4
  1. At the beginning, you should right-click on your project resources which name res then from new option choose Android Resource Directory and select font form Resource type and press OK, this will create font directory to placing your fonts in it.

enter image description here

  1. Put your .ttf font files in there.

enter image description here

  1. Go to project style file which exists in following path res/values/styles.xml and add styles like that:

    <style name="SansSerifFont">
        <item name="android:fontFamily">sans-serif</item>
    </style>
    
    <style name="OpenSansFont">
        <item name="android:fontFamily">@font/open_sans</item>
    </style>
    
    <style name="IranianSansFont">
        <item name="android:fontFamily">@font/iranian_sans</item>
    </style>
    
    <style name="BYekanFont">
        <item name="android:fontFamily">@font/b_yekan</item>
    </style>
    
    <style name="DroidArabicFont">
        <item name="android:fontFamily">@font/droid_arabic</item>
    </style>
    
  2. Go to your code and write a class like this for changing whole app font:

    public class AppFontManager {
    
        private AppCompatActivity appCompatActivity;
    
        public static final String SANS_SERIF_APP_FONT = "sans_serif";
        public static final String B_YEKAN_APP_FONT = "b_yekan";
        public static final String DROID_ARABIC_APP_FONT = "droid_arabic";
        public static final String IRANIAN_SANS_APP_FONT = "iranian_sans";
        public static final String OPEN_SANS_APP_FONT = "open_sans";
    
        public AppAppearanceManager(AppCompatActivity appCompatActivity) {
            this.appCompatActivity = appCompatActivity;
        }
    
        public void setFont(String fontName){
    
            switch (fontName){
    
                case SANS_SERIF_APP_FONT:{
                    appCompatActivity.getTheme().applyStyle(R.style.SansSerifFont, true);
                    break;
                }
    
                case B_YEKAN_APP_FONT:{
                    appCompatActivity.getTheme().applyStyle(R.style.BYekanFont, true);
                    break;
                }
    
                case DROID_ARABIC_APP_FONT:{
                    appCompatActivity.getTheme().applyStyle(R.style.DroidArabicFont, true);
                    break;
                }
    
                case IRANIAN_SANS_APP_FONT:{
                appCompatActivity.getTheme().applyStyle(R.style.IranianSansFont, true);
                    break;
                }
    
                case OPEN_SANS_APP_FONT:{
                    appCompatActivity.getTheme().applyStyle(R.style.OpenSansFont, true);
                    break;
                }
            }
        }
    }
    

    Because fonts should separately set for each activities, I prefer write a class for it for more clean code.

  3. Then call the class method before activity onCreate super.onCreate(savedInstanceState):

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        new AppAppearanceManager(this).setFont(APP_DEFAULT_FONT);
        super.onCreate(savedInstanceState);
    // Do you stuff there...
    }
    

    Remember that if you want changing font during runtime, write a chosen font in SharedPreferences or etc, then pass chosen font to all activities setFont like above.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Mohsen Pakzad
  • 221
  • 4
  • 6
2

Seems like you are using android:fontFamily instead of android:typeface in your styles.xml.

Try replacing

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:fontFamily">default</item>
</style>

with

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:typeface">default</item>
</style>
Suhas
  • 1,451
  • 14
  • 22
2

If you follow the first topic, this should work : Here

Yes with reflection. This works (based on this answer):

(Note: this is a workaround due to lack of support for custom fonts, so if you want to change this situation please do star to up-vote the android issue here). Note: Do not leave "me too" comments on that issue, everyone who has stared it gets an email when you do that. So just "star" it please.

import java.lang.reflect.Field;
import android.content.Context;
import android.graphics.Typeface;

public final class FontsOverride {

public static void setDefaultFont(Context context,
        String staticTypefaceFieldName, String fontAssetName) {
    final Typeface regular = Typeface.createFromAsset(context.getAssets(),
            fontAssetName);
    replaceFont(staticTypefaceFieldName, regular);
}

protected static void replaceFont(String staticTypefaceFieldName,
        final Typeface newTypeface) {
    try {
        final Field staticField = Typeface.class
                .getDeclaredField(staticTypefaceFieldName);
        staticField.setAccessible(true);
        staticField.set(null, newTypeface);
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}
}

You then need to overload the few default fonts, for example in an application class:

public final class Application extends android.app.Application {
    @Override
    public void onCreate() {
        super.onCreate();
        FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");
        FontsOverride.setDefaultFont(this, "MONOSPACE", "MyFontAsset2.ttf");
        FontsOverride.setDefaultFont(this, "SERIF", "MyFontAsset3.ttf");
        FontsOverride.setDefaultFont(this, "SANS_SERIF", "MyFontAsset4.ttf");
    }
}

Or course if you are using the same font file, you can improve on this to load it just once.

However I tend to just override one, say "MONOSPACE", then set up a style to force that font typeface application wide:

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

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <item name="android:typeface">monospace</item>
    </style>
</resources>

API 21 Android 5.0

I've investigated the reports in the comments that it doesn't work and it appears to be incompatible with the theme android:Theme.Material.Light.

If that theme is not important to you, use an older theme, e.g.:

<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
    <item name="android:typeface">monospace</item>
</style>
Community
  • 1
  • 1
Robin Delaporte
  • 575
  • 5
  • 15
2

Create assets folder in main folder.add fonts folder in it. add your .ttf file in fonts folder.

Add following in your app Theme:

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

Create class as TypefaceUtil

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

import java.lang.reflect.Field;

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("Can not set","Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride);
        }
    }
}

Call it in application class or in the Launcher activity

        TypefaceUtil.overrideFont(getApplicationContext(), "fonts/roboto_regular.ttf", "fonts/roboto_regular.ttf"); // font from assets: "assets/fonts/Roboto-Regular.ttf
Pratibha Sarode
  • 1,819
  • 17
  • 17
2

This is how I applied font ttf to entire App

1. Create a directory named font under res directory

2. Copy font ttf e.g. varela.ttf inside this font directory

3. Check the theme in AndroidManifest.xml

    <application
        android:theme="@style/Theme.MyAppTheme">
        <activity
            ......
        </activity>
    </application>

4. Go to themes.xml inside values directory and add the font with item tag inside base theme style referred in AndroidManifest.xml

    <resources xmlns:tools="http://schemas.android.com/tools">
        <!-- Base application theme. -->
        <style name="Theme.MyAppTheme"
          parent="Theme.MaterialComponents.DayNight.DarkActionBar">
          <item name="android:fontFamily">@font/varela</item>
        </style>
    </resources>
Nafeez Quraishi
  • 5,380
  • 2
  • 27
  • 34
0

First, make a new class that overrides whatever View you want to customize. (e.g. want a Button with a custom typeface? Extend Button). For example:

public class CustomButton extends Button {
    private final static int ROBOTO = 0;
    private final static int ROBOTO_CONDENSED = 1;

    public CustomButton(Context context) {
        super(context);
    }

    public CustomButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        parseAttributes(context, attrs); //I'll explain this method later
    }

    public CustomButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        parseAttributes(context, attrs);
    }
}

Now, if you don't have one, add an XML document under res/values/attrs.xml, and add:

<resources>
    <!-- Define the values for the attribute -->
    <attr name="typeface" format="enum">
        <enum name="roboto" value="0"/>
        <enum name="robotoCondensed" value="1"/>
    </attr>

    <!-- Tell Android that the class "CustomButton" can be styled, 
         and which attributes it supports -->
    <declare-styleable name="CustomButton">
        <attr name="typeface"/>
    </declare-styleable>
</resources>

Okay, so with that out of the way, let's get back to the parseAttributes() method from earlier:

private void parseAttributes(Context context, AttributeSet attrs) {
    TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.CustomButton);

    //The value 0 is a default, but shouldn't ever be used since the attr is an enum
    int typeface = values.getInt(R.styleable.CustomButton_typeface, 0);

    switch(typeface) {
        case ROBOTO: default:
            //You can instantiate your typeface anywhere, I would suggest as a 
            //singleton somewhere to avoid unnecessary copies
            setTypeface(roboto); 
            break;
        case ROBOTO_CONDENSED:
            setTypeface(robotoCondensed);
            break;
    }

    values.recycle();
}

Now you're all set. You can add more attributes for about anything (you could add another one for typefaceStyle -- bold, italic, etc.) but now let's see how to use it:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/com.yourpackage.name"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <com.yourpackage.name.CustomButton
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click Me!"
        custom:typeface="roboto" />

</LinearLayout>

The xmlns:custom line can really be anything, but the convention is what's shown above. What matters is that it is unique, and that's why the package name is used. Now you just use the custom: prefix for your attributes, and the android: prefix for android attributes.

One last thing: if you want to use this in a style (res/values/styles.xml), you should not add the xmlns:custom line. Just reference the name of the attribute with no prefix:

<style name="MyStyle>
    <item name="typeface">roboto</item>
</style>
Archit Goel
  • 694
  • 5
  • 19
0

I have tried font override too but at the end it's not a reliable solution, sadly overriding fonts take more than that. You can either wait for Android O with custom font to comes out or use a third party library.

The last solution that I came across was this library Caligraphy , which was easy to initiate and let you use as many font as you want. While checking its source code I understood why just overriding fonts won't work so even if you don't plan to use it I recommend reading through it once..

Good luck

Keivan Esbati
  • 3,376
  • 1
  • 22
  • 36
  • Yea.. maybe. Anyway let us know if you found a reason behind this problem, Would really appreciate it. I couldn't found a solution even reading underlying codes. – Keivan Esbati Apr 16 '17 at 12:51
0

Try below code, it works for me, Hope it'll help you too.

public class BaseActivity extends AppCompatActivity {

private Typeface typeace;
@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    typeace = Typeface.createFromAsset(getAssets(), getResources().getString(R.string.font_name));
}

@Override
protected void onStart() {
    // TODO Auto-generated method stub
    super.onStart();
    overrideFonts(this,getWindow().getDecorView());
}

private 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(typeace);
        } else if (v instanceof EditText ) {
            ((EditText) v).setTypeface(typeace);
        } else if (v instanceof Button) {
            ((Button) v).setTypeface(typeace);
        }
    } catch (Exception e) {
 }
 }
}

Now extend this BaseActivity to any of your Activity or you can create same class for fragment if you are using.

Note:- If you want to set some of the view different typeface then you have to set that programmatically as below

private Typeface typeface;
typeface = Typeface.createFromAsset(getAssets(), getResources().getString(R.string.font_name_bold));
tvUserName.setTypeface(typeface);

So give it a try and let me know, If I could help you further

Bhavnik
  • 2,020
  • 14
  • 21
0

A work around for kotlin will be this

Gist of the solution https://gist.github.com/Johnyoat/040ca5224071d01b3f3dfc6cd4d026f7

Step One

Put font file under assets/fonts/your_font_file.ttf and Create a kotlin class called TypeFaceUtil

   object TypefaceUtil{

    fun overridefonts(context: Context, defaultFontToOverride:String, customFontFileNameInAssets:String){
        try {
            val customTypeface = Typeface.createFromAsset(context.assets,customFontFileNameInAssets)
            val defaultTypefaceField = Typeface::class.java.getDeclaredField(defaultFontToOverride)
            defaultTypefaceField.isAccessible = true
            defaultTypefaceField.set(null,customTypeface)
        }catch (e:Exception){
            Timber.e("Cannot set font $customFontFileNameInAssets instead of $defaultFontToOverride")
        }
    }
}

Step Two Then in your on onCreate

TypefaceUtil.overridefonts(this,"SERIF","fonts/font_file.ttf")

Step Three

add this to your style

<item name="android:typeface">serif</item>
Ali Azaz Alam
  • 1,782
  • 1
  • 16
  • 27
Johnyoat
  • 436
  • 4
  • 14
-1

Font names should be in lower case in order to show in application and work .

Mazhar Ali
  • 111
  • 2
  • 6