Shivam Garg
Shivam Garg

Reputation: 56

Apply Font Family on TextView

I am new in Android. In my app I have number of TextViews and I want to apply different font family on TextView along with number's of following condition:

1: TextView should never be extend i.e I don't want to create my custom Textview
2: I don't want to set the font on run time i.e First get the reference of textview in code then set programmitically  by using the setType method.
3: I just want to do with the XML tag like "customeFontFamily" and for this tag i can provide different font family on different TextView.

I also read this link but it shows first android default font family. After 500 mili seconds it changes the font family that I defined in XML .

Any help on this problem would be greatly appreciated! Thank you in advance!

Upvotes: 1

Views: 831

Answers (4)

Shivam Garg
Shivam Garg

Reputation: 56

I got the way to change the font family through XML tag. I created my custom factory class to achieved this. here it is:

Step 1: Create class MyFontFactory and put this code in this class

public class MyFontFactory implements LayoutInflater.Factory2 {

    private static final String DEFAULT_FONT_FAMILY = "HelveticaLTStd-Roman"; // default application font
    private static final String[] extensions = {"ttf", "otf"};
    private static final String[] classPrefixes = {"android.widget.", "android.webkit.", "android.view."};
    private static MyFontFactory instance;
    private final LinkedList<String> fontFamilies = new LinkedList<String>();
    private final HashMap<String, Typeface> cache = new HashMap<String, Typeface>(16);

    private MyFontFactory() {}

    public static MyFontFactory getInstance() {
        return instance != null ? instance : (instance = new MyFontFactory());
    }

    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
        return createView(name, context, attrs);
    }

    public View onCreateView(String name, Context context, AttributeSet attrs) {
        return createView(name, context, attrs);
    }

    public static void attachFragment(Activity activity) {
        attachToFactory(activity.getLayoutInflater());
    }

    public static void attachDialog(Dialog dialog) { 
        attachToFactory(dialog.getLayoutInflater());
    }

    public static void attachToFactory(LayoutInflater li) {
        if (!(li.getFactory2() instanceof MyFontFactory) && !(li.getFactory() instanceof MyFontFactory)) {
            li.setFactory2(getInstance());
        }
    }

    public static void pushFont(String defaultFontFamily) {
        getInstance().fontFamilies.addFirst(defaultFontFamily);
    }

    public static void popFont() {
        getInstance().fontFamilies.removeFirst();
    }

    private View createView(String name, Context context, AttributeSet attrs) {
        View v = !name.contains(".") ? null : create(name, null, context, attrs);
        if (v == null) {
            for (String prefix : classPrefixes) {
                v = create(name, prefix, context, attrs);
                if (v != null) {
                    break;
                }
            }
        }
        return setFontFamily(v, context, attrs);
    }

    private static View create(String name, String prefix, Context context, AttributeSet attrs) {
        try {
            return LayoutInflater.from(context).createView(name, prefix, attrs);
        } catch (Throwable e) { 
            e.printStackTrace();
            return null;
        }
    }

    public View setFontFamily(final View v, final Context context, AttributeSet attrs) {
        if (context.getTheme() != null && v instanceof TextView && !v.isInEditMode()) {
            TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TextView, 0, 0);
            try {
                final String ff = resolveFontFamily(
                        a != null ? a.getString(R.styleable.TextView_fontFamily) : null, context);
                final Typeface typeface = loadTypeface(context, ff);
                if (typeface != null) {
                    ((TextView)v).setTypeface(typeface);
                }
            } finally {
                if (a != null) { a.recycle(); }
            }
        }
        return v;
    }

    private String resolveFontFamily(String ff, Context context) {
        if (ff == null && !fontFamilies.isEmpty()) {
            ff = fontFamilies.getFirst();
        }
        if (ff == null) {
            ff = context.getResources().getString(R.string.DEFAULT_FONT_FAMILY);
        }
        if (ff == null) {
            ff = DEFAULT_FONT_FAMILY;
        }
        return ff;
    }

    private Typeface loadTypeface(Context context, String fontFamily) {
        if (TextUtils.isEmpty(fontFamily)) {
            return null;
        }
        Typeface typeface = cache.get(fontFamily);
        if (typeface == null) {
            for (String ext : extensions) {
                try {
                    typeface = Typeface.createFromAsset(context.getAssets(), String.format("fonts/%s.%s", fontFamily, ext));
                } catch (Throwable t) {
                    // ignore
                }
            }
        }
        if (typeface != null) {
            cache.put(fontFamily, typeface);
        }
        return typeface;
    }
}

Step 2: Now create an Activity says FounderActivity extends with Activity and place below code in this Activity.

public class FounderActivity extends Activity {

    public void onCreate(android.os.Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getLayoutInflater().setFactory2(MyFontFactory.getInstance());
    }

    public void setContentView(int id) {
        View v = LayoutInflater.from(this).inflate(id, null);
        super.setContentView(v);
    }

    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
        View v = super.onCreateView(parent, name, context, attrs);
        if (v == null) {
            MyFontFactory.getInstance().onCreateView(parent, name, context, attrs);
        }
        if (v != null) {
            MyFontFactory.getInstance().setFontFamily(v, context, attrs);
        }
        return v;
    }}

Step 3: Create any XML under values for custom tag says attrs.xml and put these lines under this file

<?xml version="1.0" encoding="utf-8"?>
<resources>

  <declare-styleable name="TextView" >
    <attr name="fontFamily" format="string"/>
  </declare-styleable>

</resources>

Step 4: just create an layout that contains any textview and set it xml tag like

android:fontFamily = "@String/helveticafont"

and create any tag under String.xml says <String name =helveticafont>HelveticaLTStd-Roman</>

Step 5: Put your font files under assets -> fonts then any supported extension file.

Step 6: Now extends all your App activity with FounderActivity in place of Activity . this is all about what i did.

Upvotes: 1

CaptainTeemo
CaptainTeemo

Reputation: 116

Probably you are looking for this

http://developer.android.com/reference/android/widget/TextView.html#attr_android:fontFamily

This attribute android:fontFamily allows you to set a FontFamily that is in your project or the system.

If you want to do it programmatically (I read that you don't want it, but probably in the future) you can check the setTypeface() method.

http://developer.android.com/reference/android/widget/TextView.html#setTypeface(android.graphics.Typeface)

Upvotes: 0

Karakuri
Karakuri

Reputation: 38595

Your requirements:

1: I don't want to create a custom Textview by extending TextView

2: I don't want to set the font at run time.

3: I only want to use a custom XML attribute like "customFontFamily"

Under these requirements, there is no solution to your problem.

None of the Views in the Android SDK have code to handle any custom XML attributes you define. If you want to use custom XML attributes, you will have to subclass TextView. If you don't subclass TextView, then you have no choice but to set the typeface at runtime. That's all there is to it.

Upvotes: 2

Atatakai Neko
Atatakai Neko

Reputation: 86

I would suggest to use Calligraphy library. It's best solution for the custom fonts. It sets fonts on runtime.

Upvotes: 1

Related Questions