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

后端 未结 25 2950
日久生厌
日久生厌 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:08

    A brilliant solution can be found here: https://coderwall.com/p/qxxmaa/android-use-a-custom-font-everywhere.

    Simply extend activities from BaseActivity and write those methods. Also you should better cache fonts as described here: https://stackoverflow.com/a/16902532/2914140.


    After some research I wrote code that works at Samsung Galaxy Tab A (Android 5.0). Used code of weston and Roger Huang as well as https://stackoverflow.com/a/33236102/2914140. Also tested on Lenovo TAB 2 A10-70L, where it doesn't work. I inserted a font 'Comic Sans' here in order to see a difference.

    import android.content.Context;
    import android.graphics.Typeface;
    import android.os.Build;
    import android.util.Log;
    import java.lang.reflect.Field;
    import java.util.HashMap;
    import java.util.Map;
    
    public class FontsOverride {
        private static final int BOLD = 1;
        private static final int BOLD_ITALIC = 2;
        private static final int ITALIC = 3;
        private static final int LIGHT = 4;
        private static final int CONDENSED = 5;
        private static final int THIN = 6;
        private static final int MEDIUM = 7;
        private static final int REGULAR = 8;
    
        private Context context;
    
        public FontsOverride(Context context) {
            this.context = context;
        }
    
        public void loadFonts() {
            Map fontsMap = new HashMap<>();
            fontsMap.put("sans-serif", getTypeface("comic.ttf", REGULAR));
            fontsMap.put("sans-serif-bold", getTypeface("comic.ttf", BOLD));
            fontsMap.put("sans-serif-italic", getTypeface("comic.ttf", ITALIC));
            fontsMap.put("sans-serif-light", getTypeface("comic.ttf", LIGHT));
            fontsMap.put("sans-serif-condensed", getTypeface("comic.ttf", CONDENSED));
            fontsMap.put("sans-serif-thin", getTypeface("comic.ttf", THIN));
            fontsMap.put("sans-serif-medium", getTypeface("comic.ttf", MEDIUM));
            overrideFonts(fontsMap);
        }
    
        private void overrideFonts(Map typefaces) {
            if (Build.VERSION.SDK_INT == 21) {
                try {
                    final Field field = Typeface.class.getDeclaredField("sSystemFontMap");
                    field.setAccessible(true);
                    Map oldFonts = (Map) field.get(null);
                    if (oldFonts != null) {
                        oldFonts.putAll(typefaces);
                    } else {
                        oldFonts = typefaces;
                    }
                    field.set(null, oldFonts);
                    field.setAccessible(false);
                } catch (Exception e) {
                    Log.e("TypefaceUtil", "Cannot set custom fonts");
                }
            } else {
                try {
                    for (Map.Entry entry : typefaces.entrySet()) {
                        final Field staticField = Typeface.class.getDeclaredField(entry.getKey());
                        staticField.setAccessible(true);
                        staticField.set(null, entry.getValue());
                    }
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    
        private Typeface getTypeface(String fontFileName, int fontType) {
            final Typeface tf = Typeface.createFromAsset(context.getAssets(), "fonts/" + fontFileName);
            return Typeface.create(tf, fontType);
        }
    }
    

    To run the code in entire application you should write in some class like Application the following:

        new FontsOverride(this).loadFonts();
    

    Create a folder 'fonts' inside 'assets' and put needed fonts there. A simple instruction may be found here: https://stackoverflow.com/a/31697103/2914140.

    The Lenovo device also incorrectly gets a value of a typeface. In most times it returns Typeface.NORMAL, sometimes null. Even if a TextView is bold (in xml-file layout). See here: TextView isBold always returns NORMAL. This way a text on a screen is always in a regural font, not bold or italic. So I think it's a bug of a producer.

提交回复
热议问题