Android: Want to set custom fonts for whole application not runtime Android: Want to set custom fonts for whole application not runtime android android

Android: Want to set custom fonts for whole application not runtime


EDIT: So it's been a while, and I'd like to add what I think is the best way to do this, and through XML no less!

So first, you're going to want to make a new class that overrides whatever View you want to customize. (e.g. want a Button with a custom typeface? Extend Button). Let's make an 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>

                               (PREVIOUS ANSWER)

Using a custom typeface in Android

This should help. Basically, there's no way to do this in XML, and as far as I can tell, no easier way to do it in code. You could always have a setLayoutFont() method that creates the typeface once, then runs setTypeface() for each. You'd just have to update it each time you add a new item to a layout. Something like below:

public void setLayoutFont() {    Typeface tf = Typeface.createFromAsset(        getBaseContext().getAssets(), "fonts/BPreplay.otf");    TextView tv1 = (TextView)findViewById(R.id.tv1);    tv1.setTypeface(tf);    TextView tv2 = (TextView)findViewById(R.id.tv2);    tv2.setTypeface(tf);    TextView tv3 = (TextView)findViewById(R.id.tv3);    tv3.setTypeface(tf);}

EDIT: So I just got around to implementing something like this myself, and how I ended up doing it was making a function such as this:

public static void setLayoutFont(Typeface tf, TextView...params) {    for (TextView tv : params) {        tv.setTypeface(tf);    }}

Then, just use this method from onCreate(), and pass all the TextViews you want to update:

Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/BPreplay.otf");//find views by id...setLayoutFont(tf, tv1, tv2, tv3, tv4, tv5);

EDIT 9/5/12:

So since this is still getting views and votes, I'd like to add a much better and more complete method:

Typeface mFont = Typeface.createFromAsset(getAssets(), "fonts/BPreplay.otf");ViewGroup root = (ViewGroup)findViewById(R.id.myrootlayout);setFont(root, mFont);/* * Sets the font on all TextViews in the ViewGroup. Searches * recursively for all inner ViewGroups as well. Just add a * check for any other views you want to set as well (EditText, * etc.) */public void setFont(ViewGroup group, Typeface font) {    int count = group.getChildCount();    View v;    for(int i = 0; i < count; i++) {        v = group.getChildAt(i);        if(v instanceof TextView || v instanceof Button /*etc.*/)            ((TextView)v).setTypeface(font);        else if(v instanceof ViewGroup)            setFont((ViewGroup)v, font);    }}

If you pass it the root of your layout, it will recursively check for TextView or Button views (or any others you add to that if statement) within that layout, and set the font without you having to specify them by ID. This of course is assuming you want to set the font to every view.


There is a fairly easy way to do this via XML. You just need to create your own widget that extends TextView.

First, create a file in res/values/attrs.xml with the following content:

<resources>    <declare-styleable name="TypefacedTextView">        <attr name="typeface" format="string" />    </declare-styleable></resources>

After that, create your custom widget:

package your.package.widget;public class TypefacedTextView extends TextView {    public TypefacedTextView(Context context, AttributeSet attrs) {        super(context, attrs);        //Typeface.createFromAsset doesn't work in the layout editor. Skipping...        if (isInEditMode()) {            return;        }        TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.TypefacedTextView);        String fontName = styledAttrs.getString(R.styleable.TypefacedTextView_typeface);        styledAttrs.recycle();        if (fontName != null) {            Typeface typeface = Typeface.createFromAsset(context.getAssets(), fontName);            setTypeface(typeface);        }    }}

As you can see, the code above will read a font inside the assets/ folder. For this example, I am assuming that there is a file called "custom.ttf" in the assets folder. At last, use the widget in the XMLs:

<your.package.widget.TypefacedTextView    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:your_namespace="http://schemas.android.com/apk/res/your.package"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:text="Custom fonts in XML are easy"    android:textColor="#FFF"    android:textSize="14dip"    your_namespace:typeface="custom.ttf" />

Note: you won't be able to see your custom font in Eclipse's layout editor. This is why I put the isInEditMode() check. But if you run your app, the custom font will work like a charm.

Hope it helps!


Example of TextView with roboto typeface:

attr.xml

<?xml version="1.0" encoding="utf-8"?><resources><declare-styleable name="RobotoTextView">    <attr name="typeface"/></declare-styleable><attr name="typeface" format="enum">    <enum name="roboto_thin" value="0"/>    <enum name="roboto_thin_italic" value="1"/>    <enum name="roboto_light" value="2"/>    <enum name="roboto_light_italic" value="3"/>    <enum name="roboto_regular" value="4"/>    <enum name="roboto_italic" value="5"/>    <enum name="roboto_medium" value="6"/>    <enum name="roboto_medium_italic" value="7"/>    <enum name="roboto_bold" value="8"/>    <enum name="roboto_bold_italic" value="9"/>    <enum name="roboto_black" value="10"/>    <enum name="roboto_black_italic" value="11"/>    <enum name="roboto_condensed" value="12"/>    <enum name="roboto_condensed_italic" value="13"/>    <enum name="roboto_condensed_bold" value="14"/>    <enum name="roboto_condensed_bold_italic" value="15"/></attr></resources>

RobotoTextView.java:

public class RobotoTextView extends TextView {/* * Permissible values ​​for the "typeface" attribute. */private final static int ROBOTO_THIN = 0;private final static int ROBOTO_THIN_ITALIC = 1;private final static int ROBOTO_LIGHT = 2;private final static int ROBOTO_LIGHT_ITALIC = 3;private final static int ROBOTO_REGULAR = 4;private final static int ROBOTO_ITALIC = 5;private final static int ROBOTO_MEDIUM = 6;private final static int ROBOTO_MEDIUM_ITALIC = 7;private final static int ROBOTO_BOLD = 8;private final static int ROBOTO_BOLD_ITALIC = 9;private final static int ROBOTO_BLACK = 10;private final static int ROBOTO_BLACK_ITALIC = 11;private final static int ROBOTO_CONDENSED = 12;private final static int ROBOTO_CONDENSED_ITALIC = 13;private final static int ROBOTO_CONDENSED_BOLD = 14;private final static int ROBOTO_CONDENSED_BOLD_ITALIC = 15;/** * List of created typefaces for later reused. */private final static SparseArray<Typeface> mTypefaces = new SparseArray<Typeface>(16);/** * Simple constructor to use when creating a view from code. * * @param context The Context the view is running in, through which it can *                access the current theme, resources, etc. */public RobotoTextView(Context context) {    super(context);}/** * Constructor that is called when inflating a view from XML. This is called * when a view is being constructed from an XML file, supplying attributes * that were specified in the XML file. This version uses a default style of * 0, so the only attribute values applied are those in the Context's Theme * and the given AttributeSet. * <p/> * <p/> * The method onFinishInflate() will be called after all children have been * added. * * @param context The Context the view is running in, through which it can *                access the current theme, resources, etc. * @param attrs   The attributes of the XML tag that is inflating the view. * @see #RobotoTextView(Context, AttributeSet, int) */public RobotoTextView(Context context, AttributeSet attrs) {    super(context, attrs);    parseAttributes(context, attrs);}/** * Perform inflation from XML and apply a class-specific base style. This * constructor of View allows subclasses to use their own base style when * they are inflating. * * @param context  The Context the view is running in, through which it can *                 access the current theme, resources, etc. * @param attrs    The attributes of the XML tag that is inflating the view. * @param defStyle The default style to apply to this view. If 0, no style *                 will be applied (beyond what is included in the theme). This may *                 either be an attribute resource, whose value will be retrieved *                 from the current theme, or an explicit style resource. * @see #RobotoTextView(Context, AttributeSet) */public RobotoTextView(Context context, AttributeSet attrs, int defStyle) {    super(context, attrs, defStyle);    parseAttributes(context, attrs);}/** * Parse the attributes. * * @param context The Context the view is running in, through which it can access the current theme, resources, etc. * @param attrs   The attributes of the XML tag that is inflating the view. */private void parseAttributes(Context context, AttributeSet attrs) {    TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.RobotoTextView);    int typefaceValue = values.getInt(R.styleable.RobotoTextView_typeface, 0);    values.recycle();    setTypeface(obtaintTypeface(context, typefaceValue));}/** * Obtain typeface. * * @param context       The Context the view is running in, through which it can *                      access the current theme, resources, etc. * @param typefaceValue values ​​for the "typeface" attribute * @return Roboto {@link Typeface} * @throws IllegalArgumentException if unknown `typeface` attribute value. */private Typeface obtaintTypeface(Context context, int typefaceValue) throws IllegalArgumentException {    Typeface typeface = mTypefaces.get(typefaceValue);    if (typeface == null) {        typeface = createTypeface(context, typefaceValue);        mTypefaces.put(typefaceValue, typeface);    }    return typeface;}/** * Create typeface from assets. * * @param context       The Context the view is running in, through which it can *                      access the current theme, resources, etc. * @param typefaceValue values ​​for the "typeface" attribute * @return Roboto {@link Typeface} * @throws IllegalArgumentException if unknown `typeface` attribute value. */private Typeface createTypeface(Context context, int typefaceValue) throws IllegalArgumentException {    Typeface typeface;    switch (typefaceValue) {        case ROBOTO_THIN:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Thin.ttf");            break;        case ROBOTO_THIN_ITALIC:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-ThinItalic.ttf");            break;        case ROBOTO_LIGHT:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Light.ttf");            break;        case ROBOTO_LIGHT_ITALIC:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-LightItalic.ttf");            break;        case ROBOTO_REGULAR:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Regular.ttf");            break;        case ROBOTO_ITALIC:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Italic.ttf");            break;        case ROBOTO_MEDIUM:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Medium.ttf");            break;        case ROBOTO_MEDIUM_ITALIC:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-MediumItalic.ttf");            break;        case ROBOTO_BOLD:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Bold.ttf");            break;        case ROBOTO_BOLD_ITALIC:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldItalic.ttf");            break;        case ROBOTO_BLACK:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Black.ttf");            break;        case ROBOTO_BLACK_ITALIC:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BlackItalic.ttf");            break;        case ROBOTO_CONDENSED:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Condensed.ttf");            break;        case ROBOTO_CONDENSED_ITALIC:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-CondensedItalic.ttf");            break;        case ROBOTO_CONDENSED_BOLD:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldCondensed.ttf");            break;        case ROBOTO_CONDENSED_BOLD_ITALIC:            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldCondensedItalic.ttf");            break;        default:            throw new IllegalArgumentException("Unknown `typeface` attribute value " + typefaceValue);    }    return typeface;}}

Example of use:

<your.package.widget.RobotoTextView                android:layout_width="wrap_content"                android:layout_height="wrap_content"                app:typeface="roboto_thin"                android:textSize="22sp"                android:text="Roboto Thin"/>

Resources:Roboto & Noto fonts