As reported
here in issue 9904 there is a memory leak if we call
Typeface.createFromAsset() multiple times as the fonts are kept open.
To avoid this problem and to keep from accessing assstes multiple times we'll create
FontsHelper, a class that will contain all typefaces needed by the app.
public class FontsHelper {
public static final String ROBOTO_LIGHT = "fonts/Roboto-Light.ttf";
public static final String ROBOTO_BOLD = "fonts/Roboto-Bold.ttf";
public static final String ROBOTO_CONDENSED = "fonts/Roboto-Condensed.ttf";
private static Map fonts = new HashMap();
public static Typeface getTypeFace(Context context, String fontPath) {
if (!fonts.containsKey(fontPath)) {
Typeface font = Typeface.createFromAsset(context.getAssets(), fontPath);
fonts.put(fontPath, font);
}
return fonts.get(fontPath);
}
public static void setFont(View view, Typeface font) {
if (view instanceof ViewGroup)
{
for (int i = 0; i < ((ViewGroup)view).getChildCount(); i++) {
setFont(((ViewGroup)view).getChildAt(i), font);
}
} else if (view instanceof TextView) {
((TextView) view).setTypeface(font);
}
}
public static void setFont(Context ctx, TextView view, AttributeSet attrs) {
TypedArray styleAttrs = context.obtainStyledAttributes(attrs, R.styleable.CustomFontView);
String customFont = styleAttrs.getString(R.styleable.CustomFontView_customFont);
setFont(context, view, customFont);
styleAttrs.recycle();
}
public static boolean setFont(Context ctx, TextView view, String fontPath) {
boolean successful = true;
try {
Typeface tf = AssetsHelper.getTypeFace(ctx, fontPath);
view.setTypeface(tf);
} catch (Exception e) {
Log.e(TAG, "Error to get typeface: " + e.getMessage());
successful = false;
}
return successful;
}
This way we avoid the memory leaks and can further simplify the CustomFontTextView class from the previous post.
public class CustomFontTextView extends TextView {
public CustomFontTextView(Context context, AttributeSet attrs) {
super(context, attrs);
FontsHelper.setFont(context, this, attrs);
}
public CustomFontTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
FontsHelper.setFont(context, this, attrs);
}
public CustomFontTextView(Context context, String fontPath) {
super(context);
FontsHelper.setFont(context, this, fontPath);
}
}
With the custom font static variables in FontsHelper and the constructor with a fontPath argument in CustomFontTextView we can also apply the font by code in an easier way.