Accessing a font under assets folder from XML file in Android
Asked Answered
C

14

38

I am trying to do a application-wide font change and creating a style file to do so. In this file (below) I just want to change typeface value of TextAppearance style of Android.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="NightRiderFont" parent="@android:style/TextAppearance">
        <item name="android:typeface"> /***help need here***/ </item>
    </style>
</resources>

However font is in "assets/fonts/". How can I access this font, so I can use that style as a theme to get rid of changing all TextViews by hand programatically.

As summary: How can I access 'a file from assets folder' in XML?

Cundiff answered 19/7, 2011 at 11:52 Comment(0)
D
79

In my research, there is no way to add external font to the xml file. Only the 3 default font is available in xml

But you can use in java using this code.

Typeface tf = Typeface.createFromAsset(getAssets(),"fonts/verdana.ttf");  
textfield.setTypeface(tf,Typeface.BOLD);

Update:

Now I find a way to do this by creating a custom class extending the TextView and use that in the xml file.

public class TextViewWithFont extends TextView {
    private int defaultDimension = 0;
    private int TYPE_BOLD = 1;
    private int TYPE_ITALIC = 2;
    private int FONT_ARIAL = 1;
    private int FONT_OPEN_SANS = 2;
    private int fontType;
    private int fontName;

    public TextViewWithFont(Context context) {
        super(context);
        init(null, 0);
    }
    public TextViewWithFont(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }
    public TextViewWithFont(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs, defStyle);
    }
    private void init(AttributeSet attrs, int defStyle) {
        // Load attributes
        final TypedArray a = getContext().obtainStyledAttributes(
                attrs, R.styleable.font, defStyle, 0);
        fontName = a.getInt(R.styleable.font_name, defaultDimension);
        fontType = a.getInt(R.styleable.font_type, defaultDimension);
        a.recycle();
        MyApplication application = (MyApplication ) getContext().getApplicationContext();
        if (fontName == FONT_ARIAL) {
            setFontType(application .getArialFont());
        } else if (fontName == FONT_OPEN_SANS) {
            setFontType(application .getOpenSans());
        }
    }
    private void setFontType(Typeface font) {
        if (fontType == TYPE_BOLD) {
            setTypeface(font, Typeface.BOLD);
        } else if (fontType == TYPE_ITALIC) {
            setTypeface(font, Typeface.ITALIC);
        } else {
            setTypeface(font);
        }
    }
}

and in xml

<com.example.customwidgets.TextViewWithFont
        font:name="Arial"
        font:type="bold"
        android:layout_width="wrap_content"
        android:text="Hello world "
        android:padding="5dp"
        android:layout_height="wrap_content"/>

dont forget to add the schema in root of your xml

xmlns:font="http://schemas.android.com/apk/res-auto"

And create an attrs.xml file inside values directory, which is holding our custom attribues:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="font">
        <attr name="type">
        <enum name="bold" value="1"/>
            <enum name="italic" value="2"/>
        </attr>
        <attr name="name">
            <enum name="Arial" value="1"/>
            <enum name="OpenSans" value="2"/>
        </attr>
    </declare-styleable>
</resources>

Update:

Found some performance issue when this custom view is used in listview, that is because the font Object is creating every time the view is loaded. Solution I found is to initialize the font in Application Class and refer that font object by

MyApplication application = (MyApplication) getContext().getApplicationContext();

Application class will look like this

public class MyApplication extends Application {

    private Typeface arialFont, openSans;

    public void onCreate() {
        super.onCreate();

        arialFont = Typeface.createFromAsset(getAssets(), QRUtils.FONT_ARIAL);
        openSans = Typeface.createFromAsset(getAssets(), QRUtils.FONT_OPEN_SANS);
    }

    public Typeface getArialFont() {
        return arialFont;
    }

    public Typeface getOpenSans() {
        return openSans;
    }
}
Dropsical answered 19/7, 2011 at 12:0 Comment(4)
Yes, it is pain to change all single font, but it seems there is nothing else to do.Cundiff
Ya i know. I was also having the same situation before.Dropsical
Thanks,this worked for me. But has anyone come across official documentation as to why you can't set a custom typeface in an XML file?Yb
Thanks! I changed it to work with any font, just by typing the font path into the XML: https://mcmap.net/q/404346/-accessing-a-font-under-assets-folder-from-xml-file-in-androidSkit
S
6

Edit 2:

Finally fonts are supported by xml (also backwards compatible via support library): https://developer.android.com/preview/features/fonts-in-xml.html


Edit:

I now use the Calligraphy library . It is the easiest way for custom fonts.

What can you do:

  • Custom font in a TextView
  • Custom font in TextAppearance
  • Custom font in Styles
  • Custom font in Themes
  • FontSpannable to only apply font to a part of the text

I found another way to do this.

You have to make your own TextView using this tutorial

It is not that difficult and after this you can just use that TextView with your own font.

I don't know if anybody still watches this, but I thought it might help.

Seabrook answered 30/10, 2013 at 10:24 Comment(0)
P
5

Uses this function if you are using single font.

public static void applyFont(final Context context, final View root, final String fontName) {
        try {
            if (root instanceof ViewGroup) {
                ViewGroup viewGroup = (ViewGroup) root;
                for (int i = 0; i < viewGroup.getChildCount(); i++)
                    applyFont(context, viewGroup.getChildAt(i), fontName);
            } else if (root instanceof TextView)
                ((TextView) root).setTypeface(Typeface.createFromAsset(context.getAssets(), fontName));
        } catch (Exception e) {
            Log.e("ProjectName", String.format("Error occured when trying to apply %s font for %s view", fontName, root));
            e.printStackTrace();
        }
    }
Parthenon answered 16/1, 2014 at 5:35 Comment(1)
where I should call your function?Stellarator
M
2

Soorya is right, but if you have to put the same font on many textViews, I recommend you to put that code inside a static method that return the Typeface wanted. It will reduce lines in your code. Or even better create a class that extends Application and make a GET method that return the Typeface. That method will be reachable from any Activity inside your application (without the need of using static variables or static methods).

Mcgrew answered 21/7, 2011 at 17:44 Comment(0)
M
2

Check this out with the help of this don't need to set custom font programmatically.

https://mcmap.net/q/108362/-how-to-use-custom-font-in-a-project-written-in-android-studio

Mop answered 19/8, 2020 at 23:13 Comment(0)
O
1

fount change is very basic functionality in android which is mostly needed to each and every application.so every one want to change only once in application that reduce our development time so i would suggest you to see this link FountChanger.class.

Octachord answered 17/2, 2016 at 15:6 Comment(0)
K
1

You Have just make Public calls And attached Method like this

public class TextViewFontType {

public Typeface typeface;

public void fontTextView(final TextView textView, final String fonttype) {
    typeface = Typeface.createFromAsset(textView.getContext().getAssets(), fonttype);
    textView.setTypeface(typeface);
}

have you use any where method TextView set font-family.

public class FontList {

    public static final String gothicbNormal="fonts/gothicb.ttf";
    public static final String gothicbBold="fonts/gothicb.ttf";
}

made FontList calss after you have just call methods any where with pass two parameter.

Kain answered 1/9, 2016 at 4:59 Comment(0)
S
1

I took droid kid's answer and made it work with ANY font, just by typing the font filename directly into the XML:

layout.xml

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto" >

    <!-- where font file is at "assets/fonts/arial.ttf" -->
    <com.odbol.widgets.TextViewWithFont
        ...
        custom:fontFilePath="fonts/arial.ttf" />

</RelativeLayout>

Fonts.java

public class Fonts {

    // use Weak so fonts are freed from memory when you stop using them
    private final static Map<String, Typeface> fonts = new WeakHashMap<>(5);

    /***
     * Returns a font at the given path within the assets directory.
     *
     * Caches fonts to save resources.
     *
     * @param context
     * @param fontPath Path to a font file relative to the assets directory, e.g. "fonts/Arial.ttf"
     * @return
     */
    public synchronized static Typeface getFont(Context context, String fontPath) {
        Typeface font = fonts.get(fontPath);

        if (font == null) {
            font = Typeface.createFromAsset(context.getAssets(), fontPath);
            fonts.put(fontPath, font);
        }

        return font;
    }
}

values/attrs.xml

<resources>

    <declare-styleable name="TextViewWithFont">
        <!-- a path to a font, relative to the assets directory -->
        <attr name="fontFilePath" format="string" />

        <attr name="type">
            <enum name="bold" value="1"/>
            <enum name="italic" value="2"/>
        </attr>
    </declare-styleable>
</resources>

TextViewWithFont.java

public class TextViewWithFont extends TextView {
    private int defaultDimension = 0;
    private int TYPE_BOLD = 1;
    private int TYPE_ITALIC = 2;
    private int fontType;
    private int fontName;

    public TextViewWithFont(Context context) {
        super(context);
        init(null, 0);
    }
    public TextViewWithFont(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }
    public TextViewWithFont(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs, defStyle);
    }
    private void init(AttributeSet attrs, int defStyle) {
        // Load attributes
        final TypedArray a = getContext().obtainStyledAttributes(
                attrs, R.styleable.TextViewWithFont, defStyle, 0);
        String fontPath = a.getString(R.styleable.TextViewWithFont_fontFilePath);
        fontType = a.getInt(R.styleable.TextViewWithFont_type, defaultDimension);
        a.recycle();

        if (fontPath != null) {
            setFontType(Fonts.getFont(getContext(), fontPath));
        }
    }
    private void setFontType(Typeface font) {
        if (fontType == TYPE_BOLD) {
            setTypeface(font, Typeface.BOLD);
        } else if (fontType == TYPE_ITALIC) {
            setTypeface(font, Typeface.ITALIC);
        } else {
            setTypeface(font);
        }
    }
}
Skit answered 21/9, 2016 at 7:14 Comment(0)
K
0

hope use full to you:-

TextView text = (TextView) findViewById(R.id.custom_font);
Typeface font = Typeface.createFromAsset(getAssets(), "yourfont.ttf");
text.setTypeface(font);
Kraska answered 11/2, 2013 at 9:53 Comment(0)
C
0

You can use this library: https://github.com/InflationX/Calligraphy

You only have to add the font you want to use on your layout. Like this:

<TextView
 fontPath="fonts/verdana.ttf"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"/>
Cataplasia answered 5/5, 2016 at 10:3 Comment(0)
B
0

Instead of assets folder, you can put the .ttf file on fonts folder. To use fonts support in XML feature on devices running Android 4.1 (API level 16) and higher, use the Support Library 26+. Right click res folder, new -> Android resource directory-> select font -> Ok. put your "myfont.ttf" file in newly created font folder.

On res/values/styles.xml add,

<style name="customfontstyle" parent="@android:style/TextAppearance.Small">
<item name="android:fontFamily">@font/myfont</item>
</style>

On layout file add android:textAppearance="@style/customfontstyle",

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/customfontstyle"/>

Refer : https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml

Badenpowell answered 14/8, 2018 at 6:24 Comment(1)
error said "Error: Content is not allowed in prolog."Postwar
F
0

//accessing font file in code,

Typeface type = Typeface.createFromAsset(getResources().getAssets(),"fonts/arial.ttf");
textView.setTypeface(type);//assign typeface to textview

//in assets folder->fonts(foldername)->arial.ttf(font file name)

Filippo answered 17/12, 2018 at 9:28 Comment(0)
P
-1

1.Fisrt we can add assets folder> in that your font styles.ttfs in your app then
2.write access code for fonts in strings like :

<string name="fontregular">OpenSans-Light.ttf</string>
<string name="fontmedium">OpenSans-Regular.ttf</string>

3.Accessing some layout xml file textview code like this below:

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fontFamily="@string/fontregular"
    android:textColor="@color/normalfont"
    android:textSize="@dimen/textregular"/>

4.Add dimensions for font size :

<dimen name="textregular">14sp</dimen>
<dimen name="textheader">16sp</dimen>
<dimen name="smalltext">12sp</dimen>
<dimen name="littletext">10sp</dimen>
<dimen name="hightfont">18sp</dimen>

5.Add font color in colors :

<color name="normalfont">#666</color>
<color name="headerfont">#333</color>
<color name="aquablue">#4da8e3</color>
<color name="orange">#e96125</color>

6.Then apply changes it is easy process to change hole app. Happy coding keep smile..

Prettify answered 5/11, 2016 at 6:32 Comment(0)
S
-3

You can access your font file from assets folder to xml file.

android:fontFamily="fonts/roboto_regular.ttf"

fonts is the sub folder in assets folder.

Sinking answered 9/2, 2015 at 7:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.