Is it possible to set a custom font for entire of

2018-12-31 05:31发布

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 elsewhere in the application? When set, how do I use it in my layout XMLs?

24条回答
只若初见
2楼-- · 2018-12-31 05:55

For changing default font family of the TextViews, override textViewStyle in your app theme.

For using custom font in fontFamily, use font resources which is in support library.

The feature was added in Android 26 but backported to older versions via supportlib.

https://developer.android.com/guide/topics/resources/font-resource.html https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html#using-support-lib

查看更多
若你有天会懂
3楼-- · 2018-12-31 05:58

I wrote a class assigning typeface to the views in the current view hierarchy and based os the current typeface properties (bold, normal, you can add other styles if you want):

public final class TypefaceAssigner {

public final Typeface DEFAULT;
public final Typeface DEFAULT_BOLD;

@Inject
public TypefaceAssigner(AssetManager assetManager) {
    DEFAULT = Typeface.createFromAsset(assetManager, "TradeGothicLTCom.ttf");
    DEFAULT_BOLD = Typeface.createFromAsset(assetManager, "TradeGothicLTCom-Bd2.ttf");
}

public void assignTypeface(View v) {
    if (v instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) v).getChildCount(); i++) {
            View view = ((ViewGroup) v).getChildAt(i);
            if (view instanceof ViewGroup) {
                setTypeface(view);
            } else {
                setTypeface(view);
            }
        }
    } else {
        setTypeface(v);
    }
}

private void setTypeface(View view) {
    if (view instanceof TextView) {
        TextView textView = (TextView) view;
        Typeface typeface = textView.getTypeface();
        if (typeface != null && typeface.isBold()) {
            textView.setTypeface(DEFAULT_BOLD);
        } else {
            textView.setTypeface(DEFAULT);
        }
    }
}
}

Now in all fragments in onViewCreated or onCreateView, in all activities in onCreate and in all view adapters in getView or newView just invoke:

typefaceAssigner.assignTypeface(view);
查看更多
伤终究还是伤i
4楼-- · 2018-12-31 05:59

Yes with reflection. This works (based on this answer):

(Note: this is a workaround due to lack of support for custom fonts, so if you want to change this situation please do star to up-vote the android issue here). Note: Do not leave "me too" comments on that issue, everyone who has stared it gets an email when you do that. So just "star" it please.

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) {
        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();
        }
    }
}

You then need to overload the few default fonts, for example in an 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");
    }
}

Or course if you are using the same font file, you can improve on this to load it just once.

However I tend to just override one, say "MONOSPACE", then set up a style to force that font typeface application wide:

<resources>
    <style name="AppBaseTheme" parent="android:Theme.Light">
    </style>

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <item name="android:typeface">monospace</item>
    </style>
</resources>

API 21 Android 5.0

I've investigated the reports in the comments that it doesn't work and it appears to be incompatible with the theme android:Theme.Material.Light.

If that theme is not important to you, use an older theme, e.g.:

<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
    <item name="android:typeface">monospace</item>
</style>
查看更多
倾城一夜雪
5楼-- · 2018-12-31 05:59

Yes, its possible to set the font to the entire application.

The easiest way to accomplish this is to package the desired font(s) with your application.

To do this, simply create an assets/ folder in the project root, and put your fonts (in TrueType, or TTF, form) in the assets.

You might, for example, create assets/fonts/ and put your TTF files in there.

public class FontSampler extends Activity {
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
TextView tv=(TextView)findViewById(R.id.custom);

Typeface face=Typeface.createFromAsset(getAssets(), "fonts/HandmadeTypewriter.ttf");
tv.setTypeface(face);
}
}
查看更多
伤终究还是伤i
6楼-- · 2018-12-31 06:02

I would like to improve weston's and Roger Huang's answers for over API 21 Android lollipop with theme "Theme.AppCompat".

Below Android 4.4

<resources>
    <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
    </style>

   <!-- Application theme. -->
   <style name="AppTheme" parent="AppBaseTheme">
       <item name="android:typeface">monospace</item>
   </style>
</resources>

Over(equal) API 5.0

<resources>
    <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
    </style>

   <!-- Application theme. -->
   <style name="AppTheme" parent="AppBaseTheme">
       <item name="android:textAppearance">@style/CustomTextAppearance</item>
   </style>

   <style name="CustomTextAppearance">
       <item name="android:typeface">monospace</item>
   </style>
</resources>

And the FontsOverride util file is same as what in weston's answer. I have tested in these phones:

Nexus 5(android 5.1 Primary Android System)

ZTE V5(android 5.1 CM12.1)

XIAOMI note(android 4.4 MIUI6)

HUAWEI C8850(android 2.3.5 UNKNOWN)

查看更多
看风景的人
7楼-- · 2018-12-31 06:03

I would also suggest extending TextView and other controls, but it would be better I consider to set up font in constructs.

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

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

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

protected void init() {
    setTypeface(Typeface.createFromAsset(getContext().getAssets(), AppConst.FONT));
}
查看更多
登录 后发表回答