34

In my application I need to use helvetica font for all the textviews and edit-text fields. Is there any way to do this other than using settypeface method for every textview ? Any suggestion would be a great help.

Thanks in advance !

Chrishan
  • 4,076
  • 7
  • 48
  • 67
  • Visit this one: may be it can be helpful to you: http://stackoverflow.com/questions/2888508/how-to-change-the-font-on-the-textview/16166184#16166184 –  Apr 23 '13 at 11:16
  • No, there is no way. You have to bundle your font and do as nik says. You can also look at this thread [http://stackoverflow.com/questions/2376250/custom-fonts-and-xml-layouts-android](http://stackoverflow.com/questions/2376250/custom-fonts-and-xml-layouts-android) – Luis Ollero Aug 03 '11 at 12:22
  • for anyone needing a c#/Xamarin solution which extends textview but also makes it generic i.e. you can pass a specific font path through as an attribute on each textview on the xml, then take a look here https://github.com/Cheesebaron/Cheesebaron.FontSample – Dave Haigh Aug 12 '14 at 08:42

8 Answers8

64

I figured it out by my self. This is the code I used. I create custom TextView which has custom font as default font.

public class MyTextView extends TextView {

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

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

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

    private void init() {
        Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "font/chiller.ttf");
        setTypeface(tf ,1);

    }

}
Jainam Jhaveri
  • 1,479
  • 1
  • 18
  • 31
Chrishan
  • 4,076
  • 7
  • 48
  • 67
  • 2
    @mxg I didn't get what you said – Chrishan Feb 21 '12 at 16:11
  • 9
    @mxg by overriding TextView he's able to use MyTextView in his layout files without having to do anything programmatically in the activity/fragment to realize the custom font. – Bill Mote Jan 24 '13 at 15:41
  • Here is a good tutorial for this: http://www.barebonescoder.com/2010/05/android-development-using-custom-fonts. If you want to consider different font family types, like bold or italic, you will use different ttf files. The way you can handle that is to ask for this.getTypeface().getStyle() in init method, and use different fonts for the textview. HTH – Milton Apr 03 '13 at 18:24
  • all i can see on link above is ads and related links with no content only ads – prateek Oct 23 '15 at 07:18
27

In your activities, right after you call

setContentView(R.id.blahblah);

you should run a method to go over the whole hierarchy of widgets and deal with the font substitution, like;

setContentView(R.id.blahblah);
Utils.overrideFonts(this, findViewById(android.R.id.content));

And the mentioned "overrideFonts" method should be something like;

public static 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(FONT_REGULAR);
        }
    } catch (Exception e) {
        e.printStackTrace();
        // ignore
    }
}

In this scheme, FONT_REGULAR should be initialized somewhere safely, you may fancy a singleton or some other way to be sure that it is initialized properly...

private static void initializeFonts(final Context context) {
    FONT_REGULAR = Typeface.createFromAsset(context.getAssets(), "fonts/myfont_medium.otf");
    FONT_BOLD = Typeface.createFromAsset(context.getAssets(), "fonts/myfont_bold.otf");
}

If you use a subclass of Activity like MyAppActivity (extends Activity), then you dont need to change each and every Activity class for such customizations. Instead you may cut into it and override the behavior as such;

public class MyAppActivity extends Activity {
... ...
    @Override
    public void setContentView(final int layoutResID) {
        super.setContentView(layoutResID);
        Utils.overrideFonts(this, findViewById(android.R.id.content));
    }
... ...
}

This way you can use any activity of yours to have common behavior;

public class SettingsUI extends MyAppActivity {
... ...
} 

I hope it helps... Cheers!

lithium
  • 995
  • 7
  • 13
  • 6
    This is a good solution for simple layouts. However, if you have a ListView in your activity, this will not work. Items in the ListView are instantiated after setContent method and therefore, TextView in the list will not be affected by this method – Maggie Aug 06 '12 at 15:32
  • you are right, those need to be handled in the ...ItemAdapter class – lithium Aug 07 '12 at 13:37
  • 2
    What about the font of the actionbar? – AlikElzin-kilaka Aug 01 '13 at 13:13
  • TextViews inside fragments won't get their typefaces modified either. – Simas Jul 19 '15 at 17:09
9

create a style and use it all text attributes.

<style name="CustomText">
    <item name="android:typeface">YourFontName</item>
</style>

Use it:

<TextView style="@style/CustomText" />

Above is to use custom fonts in all activity for customization you can use....

Typeface font = Typeface.createFromAsset(getAssets(), "CustomFontName.ttf");  
txt.setTypeface(font);

TRy this.

Triode
  • 11,309
  • 2
  • 38
  • 48
Hanry
  • 5,481
  • 2
  • 40
  • 53
  • 11
    android:typeface field only allow to use inbuilt font names. How can I assign custom font name which is in asset folder ? – Chrishan Aug 04 '11 at 00:07
  • 3
    @hanry You cannot use a custom font name in the android:typeface field. The 2nd part of your answer will work, but the styles portion will not. – Bill Mote Jan 24 '13 at 15:48
  • 2
    This doesn't answer the question. "Is there any way to do this other than using settypeface method for every textview?". – Benjamin Piette Aug 21 '14 at 10:18
6

To apply custom font across all application, just create following activity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    FontManager.getInstance().initialize(this, R.xml.fonts);
    setContentView(R.layout.main);
}
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
    SimpleFactory factory = new SimpleFactory();
    return factory.onCreateView(name, context, attrs);
}

where FontManager this is class that manage all Fonts that defined in /xml/fonts.xml and SimpleFactory just factory that create views and apply custom font to each view that instance of text view.

/xml/fonts.xml

<?xml version="1.0" encoding="utf-8"?>
<familyset>
    <family>
        <nameset>
            <!--Font name-->
            <name>HelveticaNeueLTStd</name>
        </nameset>
        <fileset>
            <!--Font styles-->
            <file style="normal">fonts/HelveticaNeueLTStd-LtCn.otf</file>
            <file style="bold">fonts/HelveticaNeueLTStd-MdCn.otf</file>
            <file style="italic">fonts/HelveticaNeueLTStd-LtCnO.otf</file>
            <file style="bold_italic">fonts/HelveticaNeueLTStd-MdCnO.otf</file>
        </fileset>
    </family>
    <family>
        <!--There new font family can be added,
don't forget add font files into /assets/fonts directory and
put the name of the font into /values/string/font.xml-->
    </family>
</familyset>

FontFactory - abastract class, just extends it to create your own factory

public abstract class FontFactory implements LayoutInflater.Factory{
    public final String TAG = getClass().getSimpleName();

    static final Class<?>[] mConstructorSignature = new Class[] {Context.class, AttributeSet.class};
    final Object[] mConstructorArgs = new Object[2];
    private static final String[] sClassPrefixList = {
            "android.widget.",
            "android.webkit."
    };

    @Override
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        if("ViewStub".equals(name) || "View".equals(name)){
            return null;
        }
        View view = null;
        Constructor<? extends View> constructor = null;
        Class clazz = null;

        if (view == null) {
            if (-1 == name.indexOf('.')) {
                for (String prefix : sClassPrefixList) {
                    clazz = getClazz(prefix, name);
                    if(clazz != null){
                        break;
                    }
                }
            } else {
                clazz = getClazz("", name);
            }
        }

        if (clazz == null) {
            Log.d(TAG, "View can't be created " + name);
            return null;
        }

        try {
            constructor = clazz.getConstructor(mConstructorSignature);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        Object[] args = mConstructorArgs;
        args[1] = attrs;

        if(constructor == null){
            return null;
        }

        try {
                view = constructor.newInstance(context, attrs);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        if(view != null){
            onFontApply(context, view);
        }
        return view;
    }

    public abstract void onFontApply(Context context, View view);

    private Class getClazz(String prefix, String name){
        Class clazz = null;
        try {
            clazz = Class.forName(prefix + name);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            return clazz;
        }
    }
}

FontManager - just map font files defined in /xml/fonts.xml to font files placed in /assets directory and return TypeFace by font family name and font style.

public void initialize(Context context, int resId) {
    if(mFonts != null){
        Log.d(TAG,"FontManager have already initialized");
        return;
    }
    XmlResourceParser parser = null;
    try {
        parser = context.getResources().getXml(resId);
        mFonts = new ArrayList<Font>();

        String tag;
        String fontStryleAttr = null;
        int eventType = parser.getEventType();

        Font font = null;

        do {
            tag = parser.getName();

            switch (eventType) {
                case XmlPullParser.START_TAG:
                    if (tag.equals(TAG_FAMILY)) {
                        // one of the font-families.
                        font = new Font();
                    } else if (tag.equals(TAG_NAMESET)) {
                        // a list of font-family names supported.
                        font.families = new ArrayList<String>();
                    } else if (tag.equals(TAG_NAME)) {
                        isName = true;
                    } else if (tag.equals(TAG_FILESET)) {
                        // a list of files specifying the different styles.
                        font.styles = new ArrayList<FontStyle>();
                    } else if (tag.equals(TAG_FILE)) {
                        isFile = true;
                        fontStryleAttr = parser.getAttributeValue(null, ATTR_STYLE);
                    }
                    break;

                case XmlPullParser.END_TAG:
                    if (tag.equals(TAG_FAMILY)) {
                        // add it to the list.
                        if (font != null) {
                            mFonts.add(font);
                            font = null;
                        }
                    } else if (tag.equals(TAG_NAME)) {
                        isName = false;
                    } else if (tag.equals(TAG_FILE)) {
                        isFile = false;
                        fontStryleAttr = null;
                    }
                    break;

                case XmlPullParser.TEXT:
                    String text = parser.getText();
                    if (isName) {
                        // value is a name, add it to list of family-names.
                        if (font.families != null)
                            font.families.add(text);
                    } else if (isFile) {
                        // value is a file, add it to the proper kind.
                        FontStyle fontStyle = new FontStyle();
                        fontStyle.font = Typeface.createFromAsset(context.getAssets(), text);
                        String attr = parser.getAttributeValue(null, ATTR_STYLE);
                        if (fontStryleAttr.equals(STYLE_BOLD))
                            fontStyle.style = Typeface.BOLD;
                        else if (fontStryleAttr.equals(STYLE_ITALIC))
                            fontStyle.style = Typeface.ITALIC;
                        else if (fontStryleAttr.equals(STYLE_BOLD_ITALIC))
                            fontStyle.style = Typeface.BOLD_ITALIC;
                        else
                            fontStyle.style = Typeface.NORMAL;
                        font.styles.add(fontStyle);
                    }
            }

            eventType = parser.next();

        } while (eventType != XmlPullParser.END_DOCUMENT);

    } catch (XmlPullParserException e) {
        throw new InflateException("Error inflating font XML", e);
    } catch (IOException e) {
        throw new InflateException("Error inflating font XML", e);
    } finally {
        if (parser != null)
            parser.close();
    }
}

public Typeface get(String family, int style) {
    for (Font font: mFonts) {
        for (String familyName : font.families) {
            if (familyName.equals(family)) {
                // if no style in specified, return normal style.
                if (style == -1)
                    style = Typeface.NORMAL;
                for (FontStyle fontStyle : font.styles) {
                    if (fontStyle.style == style)
                        return fontStyle.font;
                }
            }
        }
    }
    return mDefaultFont;
}

for more code and samples just look here

Nikolay Nikiforchuk
  • 1,998
  • 24
  • 20
0

You can use PixlUI at http://bit.ly/1bzjWQn

import their .jar in your project. Use it in XML

 <com.neopixl.pixlui.components.textview.TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world"
    pixlui:typeface="MyFont.ttf" />

Don't forget implement scheme ( xmlns:pixlui="http://schemas.android.com/apk/com.neopixl.pixlui" )

odemolliens
  • 2,581
  • 2
  • 32
  • 34
0
    setContentView(R.layout.activity_main);
    custfont(this, findViewById(android.R.id.content));



private void custfont(final Context context, 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(Typeface.createFromAsset(context.getAssets(), "fonts/ostrichblack.ttf"));
        }
    }
    catch (Exception e) 
    {
    }
}
Amrish Kakadiya
  • 974
  • 1
  • 7
  • 25
0
import android.content.Context;
import android.graphics.Typeface;

/**
 * Created by Sanjeev Kumar on 4/18/2017.
 */

public class FontManager {
    public Context mContext;

    public FontManager(Context context) {
        this.mContext = context;
    }

    public Typeface getSquarkiFont() {
        return Typeface.createFromAsset(mContext.getAssets(), "fonts/Squarki.ttf");
    }

    public Typeface getLazySpringDayFont() {
        return Typeface.createFromAsset(mContext.getAssets(), "fonts/LazySpringDay.ttf");
    }
}
duggu
  • 37,851
  • 12
  • 116
  • 113
Sanjeev Kumar
  • 193
  • 1
  • 7
0

Ok you can do it but what you essentially want to make is a font atlas in a kinda map format(it will have to run in unicode order which starts !"#$% '()x+,-./). What the function will do is take in a string and work out where in the atlas each corresponding letter is.

Its not too easy but each character must have the same length and width, you could have different lengths but that will be a lot harder.

Chris
  • 1,766
  • 1
  • 21
  • 36