Is it possible to set a custom font for entire of application?

后端 未结 25 3196
日久生厌
日久生厌 2020-11-22 02:44

I need to use certain font for my entire application. I have .ttf file for the same. Is it possible to set this as default font, at application start up and then use it else

25条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2020-11-22 03:22

    In summary:

    Option#1: Use reflection to apply font (combining weston & Roger Huang's answer):

    import java.lang.reflect.Field;
    import android.content.Context;
    import android.graphics.Typeface;
    
    public final class FontsOverride { 
    
        public static void setDefaultFont(Context context,
                String staticTypefaceFieldName, String fontAssetName) {
            final Typeface regular = Typeface.createFromAsset(context.getAssets(),
                    fontAssetName);
            replaceFont(staticTypefaceFieldName, regular);
        } 
    
        protected static void replaceFont(String staticTypefaceFieldName,final Typeface newTypeface) {
            if (isVersionGreaterOrEqualToLollipop()) {
                Map newMap = new HashMap();
                newMap.put("sans-serif", newTypeface);
                try {
                    final Field staticField = Typeface.class.getDeclaredField("sSystemFontMap");
                    staticField.setAccessible(true);
                    staticField.set(null, newMap);
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            } else {
                try {
                    final Field staticField = Typeface.class.getDeclaredField(staticTypefaceFieldName);
                    staticField.setAccessible(true);
                    staticField.set(null, newTypeface);
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } 
            }
        }
    
    } 
    

    Usage in Application class:

    public final class Application extends android.app.Application {
        @Override 
        public void onCreate() { 
            super.onCreate(); 
            FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");
            FontsOverride.setDefaultFont(this, "MONOSPACE", "MyFontAsset2.ttf");
            FontsOverride.setDefaultFont(this, "SERIF", "MyFontAsset3.ttf");
            FontsOverride.setDefaultFont(this, "SANS_SERIF", "MyFontAsset4.ttf");
        } 
    } 
    

    set up a style to force that font typeface application wide (based on lovefish):

    Pre-Lollipop:

    
        
    
       
       
    
    

    Lollipop (API 21):

    
        
    
       
       
    
       
    
    

    Option2: Subclass each and every View where you need to customize font, ie. ListView, EditTextView, Button, etc. (Palani's answer):

    public class CustomFontView extends TextView {
    
    public CustomFontView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(); 
    } 
    
    public CustomFontView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(); 
    } 
    
    public CustomFontView(Context context) {
        super(context);
        init(); 
    } 
    
    private void init() { 
        if (!isInEditMode()) {
            Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "Futura.ttf");
            setTypeface(tf);
        } 
    } 
    

    Option 3: Implement a View Crawler that traverses through the view hierarchy of your current screen:

    Variation#1 (Tom's answer):

    public static final void setAppFont(ViewGroup mContainer, Typeface mFont, boolean reflect)
    { 
        if (mContainer == null || mFont == null) return;
    
        final int mCount = mContainer.getChildCount();
    
        // Loop through all of the children. 
        for (int i = 0; i < mCount; ++i)
        { 
            final View mChild = mContainer.getChildAt(i);
            if (mChild instanceof TextView)
            { 
                // Set the font if it is a TextView. 
                ((TextView) mChild).setTypeface(mFont);
            } 
            else if (mChild instanceof ViewGroup)
            { 
                // Recursively attempt another ViewGroup. 
                setAppFont((ViewGroup) mChild, mFont);
            } 
            else if (reflect)
            { 
                try { 
                    Method mSetTypeface = mChild.getClass().getMethod("setTypeface", Typeface.class);
                    mSetTypeface.invoke(mChild, mFont); 
                } catch (Exception e) { /* Do something... */ }
            } 
        } 
    } 
    

    Usage :

    final ViewGroup mContainer = (ViewGroup) findViewById(
    android.R.id.content).getRootView();
    HomeActivity.setAppFont(mContainer, Typeface.createFromAsset(getAssets(),
    "fonts/MyFont.ttf"));
    

    Variation#2: https://coderwall.com/p/qxxmaa/android-use-a-custom-font-everywhere.

    Option #4: Use 3rd Party Lib called Calligraphy.

    Personally, I would recommend Option#4, as it saves a lot of headaches.

提交回复
热议问题