Custom Fonts with Support Library is not working on a real device

Viewed 26657

I have used custom font with Support Library API 26. I have created font-family using style and add style to my text view. I found that font is going to set in Preview during design, but not working in android real devices. Below is my code and I have also attached screenshot. Thanks in advance.

TextView:

<TextView
    android:id="@+id/card_number_text"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:text="111 5235 5563 8845"
    android:gravity="left"
    android:layout_marginRight="8dp"
    app:layout_constraintRight_toRightOf="parent"
    android:layout_marginTop="8dp"
    style="@style/creditCardText"
    app:layout_constraintTop_toBottomOf="@+id/payableLayout"
    app:layout_constraintLeft_toLeftOf="@+id/payableLayout"
    app:layout_constraintHorizontal_bias="0.0" />

Style.xml:

<style name="creditCardText">
    <item name="android:textSize">@dimen/textSizeLarge</item>
    <item name="android:fontFamily">@font/font_roboto_medium</item>
    <item name="android:textColor">@color/color_card_number</item>
</style>

Font Family:

<font-family xmlns:android="http://schemas.android.com/apk/res/android">
<font
    android:fontStyle="normal"
    android:fontWeight="400"
    android:font="@font/roboto_medium" />

build.gradle:

apply plugin: 'com.android.application'
buildscript {
    repositories {
    }
    dependencies {
   }
}

android {
    signingConfigs {
    }
   compileSdkVersion 26
   defaultConfig {
        applicationId "org.saifintex.skypaytrans"
        minSdkVersion 18
        targetSdkVersion 26
        vectorDrawables.useSupportLibrary = true
        versionCode 7
        multiDexEnabled true
        versionName "1.6"
        testInstrumentationRunner 
        "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
   }

lintOptions {
    abortOnError false        // true by default
    checkAllWarnings false
    checkReleaseBuilds false
    ignoreWarnings true       // false by default
    quiet true                // false by default
}

repositories {
    maven { url "https://jitpack.io" }
}
dexOptions {
    javaMaxHeapSize "4g"
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
    debug {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

    }
}
externalNativeBuild {
    cmake {
        path "CMakeLists.txt"
    }
}
packagingOptions {
    exclude 'META-INF/DEPENDENCIES'
    exclude 'META-INF/NOTICE'
    exclude 'META-INF/LICENSE'
    exclude 'META-INF/LICENSE.txt'
    exclude 'META-INF/NOTICE.txt'
}
productFlavors {
}
sourceSets {
    main {
        assets.srcDirs = ['src/main/assets', 'src/main/assets/']
        java.srcDirs = ['src/main/java', 'src/main/java/fonts']
    }
  }
}

dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')

androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', 
{
    exclude group: 'com.android.support', module: 'support-annotations'
})
compile "com.android.support:appcompat-v7:26.1.0"
compile "com.android.support:design:26.1.0"
compile "com.android.support:recyclerview-v7:26.1.0"
compile project(':tooltip')
compile project(':mylibrary')
compile fileTree(include: ['*.jar'], dir: 'libs')
compile "com.j256.ormlite:ormlite-
android:${rootProject.ormliteAndroidVersion}"
compile "com.j256.ormlite:ormlite-core:${rootProject.ormliteCoreVersion}"
testCompile 'junit:junit:4.12'
compile 'com.afollestad.material-dialogs:core:0.9.4.2'
compile 'com.fasterxml.jackson.core:jackson-core:2.7.2'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.7.2'
compile 'com.fasterxml.jackson.core:jackson-databind:2.7.2'
compile 'com.soundcloud.android:android-crop:1.0.1@aar'
compile 'com.jakewharton:butterknife:7.0.1'
compile 'com.android.volley:volley:1.0.0'
compile 'commons-codec:commons-codec:1.10'
compile 'com.android.support:design:26.1.0'
compile 'com.squareup.picasso:picasso:2.4.0'
compile 'com.google.firebase:firebase-messaging:11.0.1'
compile 'com.google.firebase:firebase-core:11.0.1'
compile 'com.android.support:cardview-v7:26.1.0'
compile 'com.android.support:support-v4:26.1.0'
compile 'com.wang.avi:library:2.1.3'
compile 'com.github.ayalma:ExpandableRecyclerView:0.2.0'
compile 'com.github.deano2390:MaterialShowcaseView:1.1.0'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'com.google.firebase:firebase-crash:11.0.1'
compile 'com.google.firebase:firebase-auth:11.0.1'
compile 'com.google.android.gms:play-services-analytics:11.0.1'
compile 'com.alimuzaffar.lib:pinentryedittext:1.3.1'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-
core:3.0.1'
testCompile 'junit:junit:4.12'
}

configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
    def requested = details.requested
    if (requested.group == 'com.android.support') {
        if (!requested.name.startsWith("multidex") && 
        !requested.name.startsWith("crash")) {
            details.useVersion '25.3.1'
        }
    }
}
}

apply plugin: 'com.google.gms.google-services'

Font resource dir:

enter image description here

Design preview: Here font is working

enter image description here

Android Device Screenshot: Here font is not working

enter image description here

7 Answers

I spent hours trying to figure out why the font wasn't working. I was trying to migrate from Calligraphy library and you have to disable the default font setup in Application class.

setDefaultFontPath(app.getString(R.string.font_path_medium))

Replace the default font setup with this.

<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">your_front</item>
</style>

<style name="RobotoButtonStyle" parent="android:Widget.Button">
    <item name="android:fontFamily">your_font</item>
</style>

Requirement

  • 1) assets folder which has sub folder "/fonts"

  • 2) require custom fonts ".ttf" files in /fonts folder.

  • 3) enum

  • 4) attrs.xml file

  • 5) java class

  • 6) Usage


1) create assets folder in

src/main/assets

2) add custom fonts in

src/main/assets/fonts/

3) enum

import android.annotation.SuppressLint;
import android.content.Context;


@SuppressLint("StaticFieldLeak")
public enum Fonts {

OpenSans_Bold("OpenSans-Bold.ttf", 0),
OpenSans_BoldItalic("OpenSans-BoldItalic.ttf", 1),
OpenSans_CondBold("OpenSans-CondBold.ttf", 2),
OpenSans_CondLight("OpenSans-CondLight.ttf", 3),
OpenSans_CondLightItalic("OpenSans-CondLightItalic.ttf", 4),
OpenSans_ExtraBold("OpenSans-ExtraBold.ttf", 5),
OpenSans_ExtraBoldItalic("OpenSans-ExtraBoldItalic.ttf", 6),
OpenSans_Italic("OpenSans-Italic.ttf", 7),
OpenSans_Light("OpenSans-Light.ttf", 8),
OpenSans_LightItalic("OpenSans-LightItalic.ttf", 9),
OpenSans_Regular("OpenSans-Regular.ttf", 10),
OpenSans_Semibold("OpenSans-Semibold.ttf", 11),
OpenSans_SemiboldItalic("OpenSans-SemiboldItalic.ttf", 12),

AudioWide_Regular("Audiowide_Regular.ttf", 13);

String stringValue;
int value;
Context context;

Fonts(Context context) {
    this.context = context;
}

Fonts(String toString, int value) {
    stringValue = toString;
    this.value = value;
}

@Override
public String toString() {
    return "fonts/" + stringValue;
}

}

4) attrs.xml file

create attrs.xml in res/values folder

<resources>
<declare-styleable name="FontTextView">

    <attr name="customFont" format="enum">
        <enum name="OpenSans_Bold" value="0" />
        <enum name="OpenSans_BoldItalic" value="1" />
        <enum name="OpenSans_CondBold" value="2" />
        <enum name="OpenSans_CondLight" value="3" />
        <enum name="OpenSans_CondLightItalic" value="4" />
        <enum name="OpenSans_ExtraBold" value="5" />
        <enum name="OpenSans_ExtraBoldItalic" value="6" />
        <enum name="OpenSans_Italic" value="7" />
        <enum name="OpenSans_Light" value="8" />
        <enum name="OpenSans_LightItalic" value="9" />
        <enum name="OpenSans_Regular" value="10" />
        <enum name="OpenSans_Semibold" value="11" />
        <enum name="OpenSans_SemiboldItalic" value="12" />
        <enum name="Audiowide_Regular" value="13" />

    </attr>

</declare-styleable>


5) FontTextView.java

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;
import com.example.Fonts;
import com.example.R;

@SuppressLint("AppCompatCustomView")
public class FontTextView extends TextView {

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

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

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

private void init(Context context, AttributeSet attrs) {

    TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.FontTextView, 0, 0);

    String fontText = a.getString(R.styleable.FontTextView_customFont);

    if (fontText != null) {
        switch (fontText) {
            case "0":
                fontText = Fonts.OpenSans_Bold.toString();
                break;
            case "1":
                fontText = Fonts.OpenSans_BoldItalic.toString();
                break;
            case "2":
                fontText = Fonts.OpenSans_CondBold.toString();
                break;
            case "3":
                fontText = Fonts.OpenSans_CondLight.toString();
                break;
            case "4":
                fontText = Fonts.OpenSans_CondLightItalic.toString();
                break;
            case "5":
                fontText = Fonts.OpenSans_ExtraBold.toString();
                break;
            case "6":
                fontText = Fonts.OpenSans_ExtraBoldItalic.toString();
                break;
            case "7":
                fontText = Fonts.OpenSans_Italic.toString();
                break;
            case "8":
                fontText = Fonts.OpenSans_Light.toString();
                break;
            case "9":
                fontText = Fonts.OpenSans_LightItalic.toString();
                break;
            case "10":
                fontText = Fonts.OpenSans_Regular.toString();
                break;
            case "11":
                fontText = Fonts.OpenSans_Semibold.toString();
                break;
            case "13":
                fontText = Fonts.AudioWide_Regular.toString();
                break;
            case "12":
                fontText = Fonts.OpenSans_SemiboldItalic.toString();
                break;
            default:
                fontText = Fonts.OpenSans_Regular.toString();
                break;
        }

        Log.e("String", fontText);
        Typeface tf = Typeface.createFromAsset(getContext().getAssets(), fontText);

        setTypeface(tf);
    }
    a.recycle();
}

}

6) Usage

    <com.example.FontTextView
         android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:padding="10sp"
        android:text="this is custom font"
        android:textSize="20sp"
        app:customFont="OpenSans_Semibold" />

add below namespace to the top parents Layout of xml file xmlns:app="http://schemas.android.com/apk/res-auto"

reference by :

"Android Custom TypeFace fontFamily "

click here

with this, you can easily add any font in android.

Based on a similar issue I had, while also using the support library, I noticed this in the documentation:

Note: When you declare font families in XML layout through the support library, use the app namespace to ensure your fonts load.

So I had a look and updated the fontFamily attribute to use app: instead of android, so in your case:

<item name="app:fontFamily">@font/font_roboto_medium</item>

instead of:

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

Hope that helps! Seems to be a weird implementation of the support library causing the confusion here.

https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml#using-support-lib

A bit late to the party, but I've encountered an issue with using fontFamily in FragmentActivities. In those activities the font is not correctly shown. If you let your activity extend from AppCompatActivity (which extends FragmentActivity) than the font is correctly shown.

If you are using butterknife view injection for binding your custom text or button view, you should override onFinishInflate() method in custom view class.
For example:

@Override
protected void onFinishInflate() {
    super.onFinishInflate();
    Typeface font_type = Typeface.createFromAsset(getContext().getAssets(), "fonts/" + fontStyle);
    this.setTypeface(font_type);
}
Related