是否可以为整个应用程序设置自定义字体?

我需要为我的整个应用程序使用特定的字体。 我有.ttf文件相同。 在应用程序启动时,是否可以将其设置为默认字体,然后在应用程序的其他地方使用它? 设置后,如何在我的布局XML中使用它?

是的,反思。 这工作( 基于这个答案 ):

(注意:这是一个解决方法,由于缺乏自定义字体的支持,所以如果你想改变这种情况,请做明星在这里投票android问题 )。 注意:不要在这个问题上留下“我也是”的评论,每个看过它的人都会收到一封电子邮件。 所以就请“星”吧。

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

然后,您需要重载几个默认字体,例如在一个应用程序类中:

 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"); } } 

或者当然,如果你使用的是相同的字体文件,你可以改善这个只加载一次。

不过,我倾向于重写一个,说"MONOSPACE" ,然后设置一个风格,以强制该字体字体应用程序:

 <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

我已经在评论中调查报告,它不工作,它似乎与主题android:Theme.Material.Light不兼容。

如果这个主题对你来说不重要,可以使用一个旧的主题,例如:

 <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar"> <item name="android:typeface">monospace</item> </style> 

在android: 书法中有一个很好的自定义字体库

这里是一个如何使用它的示例。

在Gradle中,你需要把这一行放到你应用程序的build.gradle文件中:

 dependencies { compile 'uk.co.chrisjenx:calligraphy:2.2.0' } 

然后创build一个扩展Application的类并写下这个代码:

 public class App extends Application { @Override public void onCreate() { super.onCreate(); CalligraphyConfig.initDefault(new CalligraphyConfig.Builder() .setDefaultFontPath("your font path") .setFontAttrId(R.attr.fontPath) .build() ); } } 

并且在activity类中把这个方法放在onCreate之前:

 @Override protected void attachBaseContext(Context newBase) { super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase)); } 

而你的清单文件的最后一件事情应该是这样的:

 <application . . . android:name=".App"> 

它会改变整个活动到你的字体! 它很简单,干净!

虽然这不适用于整个应用程序,但它可以用于“活动”,并可以重新用于其他任何“活动”。 我更新了我的代码感谢@ FR073N支持其他视图。 我不知道与ButtonsRadioGroups等问题,因为这些类都扩展TextView所以他们应该工作得很好。 我添加了一个布尔条件来使用reflection,因为它看起来非常黑客,可能会影响性能。

注意:正如指出的,这不适用于dynamic内容! 为此,可以使用onCreateViewgetView方法来调用此方法,但需要额外的努力。

 /** * Recursively sets a {@link Typeface} to all * {@link TextView}s in a {@link ViewGroup}. */ 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... */ } } } } 

然后使用它,你会做这样的事情:

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

希望有所帮助。

我想提高weston对API 21 Android 5.0的回答。

原因

在API 21下,大多数文本样式包括fontFamily设置,如:

 <style name="TextAppearance.Material"> <item name="fontFamily">@string/font_family_body_1_material</item> </style> 

其中应用默认的Roboto Regular字体:

 <string name="font_family_body_1_material">sans-serif</string> 

原始答案未能应用等宽字体,因为android:fontFamily对android:typeface属性( 引用 )有更高的优先权。 使用Theme.Holo。*是一个有效的解决方法,因为里面没有android:fontFamily设置。

由于Android 5.0将系统字体放在静态variablesTypeface.sSystemFontMap( reference )中,我们可以使用相同的reflection技术来replace它:

 protected static void replaceFont(String staticTypefaceFieldName, final Typeface newTypeface) { if (isVersionGreaterOrEqualToLollipop()) { Map<String, Typeface> newMap = new HashMap<String, Typeface>(); 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(); } } } 

综上所述:

选项1:使用reflection来应用字体(结合weston和Roger Huang的答案):

 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<String, Typeface> newMap = new HashMap<String, Typeface>(); 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(); } } } } 

应用程序类中的用法:

 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"); } } 

设置一个风格强制该字体字体应用程序(基于lovefish ):

预棒棒糖:

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

棒棒糖(API 21):

 <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> 

选项2:子类每个视图,你需要自定义字体,即。 ListView,EditTextView,Button等( Palani的回答):

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

选项3:实现遍历当前屏幕的视图层次结构的视图爬行器​​:

变化#1( 汤姆的回答):

 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... */ } } } } 

用法:

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

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

选项#4:使用称为书法的第三方图书馆。

就个人而言,我会build议选项#4,因为它可以节省很多头痛。

它非常简单… 1.下载并把你的自定义字体资产..然后写一个单独的文本视图的类如下:这里我用futura字体

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

}

并在xml中执行以下操作:

  <com.packagename.CusFntTextView android:id="@+id/tvtitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hi Android" android:textAppearance="?android:attr/textAppearanceLarge" /> 

我也build议扩展TextView和其他控件,但它会更好,我认为在build设中设置字体。

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

我想通过主题为“ Theme.AppCompat ”来改善weston和Roger Huang对API 21 Android棒棒糖的解答。

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> 

超过(相等)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> 

FontsOverride util文件与weston的答案相同。 我在这些手机上testing过

Nexus 5(Android 5.1主Android系统)

中兴V5(android 5.1 CM12.1)

小蜜笔记(android 4.4 MIUI6)

华为C8850(android 2.3.5 UNKNOWN)

为Xamarin.Android工作:

类:

 public class FontsOverride { public static void SetDefaultFont(Context context, string staticTypefaceFieldName, string fontAssetName) { Typeface regular = Typeface.CreateFromAsset(context.Assets, fontAssetName); ReplaceFont(staticTypefaceFieldName, regular); } protected static void ReplaceFont(string staticTypefaceFieldName, Typeface newTypeface) { try { Field staticField = ((Java.Lang.Object)(newTypeface)).Class.GetDeclaredField(staticTypefaceFieldName); staticField.Accessible = true; staticField.Set(null, newTypeface); } catch (Exception e) { Console.WriteLine(e.Message); } } } 

应用程序实现

 namespace SomeAndroidApplication { [Application] public class App : Application { public App() { } public App(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer) { } public override void OnCreate() { base.OnCreate(); FontsOverride.SetDefaultFont(this, "MONOSPACE", "fonts/Roboto-Light.ttf"); } } } 

样式:

 <style name="Theme.Storehouse" parent="Theme.Sherlock"> <item name="android:typeface">monospace</item> </style> 

一个辉煌的解决scheme可以在这里find: https : //coderwall.com/p/qxxmaa/android-use-a-custom-font-everywhere 。

只需从BaseActivity扩展活动并编写这些方法即可。 你也应该更好地caching字体在这里描述: https : //stackoverflow.com/a/16902532/2914140 。


经过一番研究,我写了三星Galaxy Tab A(Android 5.0)的代码。 使用weston和Roger Huang的代码以及https://stackoverflow.com/a/33236102/2914140 。 也testing联想TAB 2 A10-70L,它不起作用。 为了看到不同,我在这里插入了一个字体“Comic Sans”。

 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<String, Typeface> 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<String, Typeface> typefaces) { if (Build.VERSION.SDK_INT == 21) { try { final Field field = Typeface.class.getDeclaredField("sSystemFontMap"); field.setAccessible(true); Map<String, Typeface> oldFonts = (Map<String, Typeface>) 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<String, Typeface> 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); } } 

要在整个应用程序中运行代码,你应该在类Application中编写如下代码:

  new FontsOverride(this).loadFonts(); 

在“资产”里面创build一个文件夹“字体”,并在其中放置所需的字体。 一个简单的指令可以在这里find: https : //stackoverflow.com/a/31697103/2914140 。

联想设备也错误地获得了字体的价值。 在大多数情况下,它返回Typeface.NORMAL,有时为空。 即使TextView是粗体(xml文件布局)。 看到这里: TextView isBold总是返回NORMAL 。 这样一个屏幕上的文本总是一个正规的字体,而不是粗体或斜体。 所以我认为这是一个生产者的错误。

你可以为每个布局一个一个地设置自定义的字体,只需要通过传递它的根View.First来创build一个singelton方法来访问字体对象

  public class Font { private static Font font; public Typeface ROBO_LIGHT; private Font() { } public static Font getInstance(Context context) { if (font == null) { font = new Font(); font.init(context); } return font; } public void init(Context context) { ROBO_LIGHT = Typeface.createFromAsset(context.getAssets(), "Roboto-Light.ttf"); } } 

您可以在上面的类中定义不同的字体,现在定义一个将应用字体的字体助手类:

  public class FontHelper { private static Font font; public static void applyFont(View parentView, Context context) { font = Font.getInstance(context); apply((ViewGroup)parentView); } private static void apply(ViewGroup parentView) { for (int i = 0; i < parentView.getChildCount(); i++) { View view = parentView.getChildAt(i); //You can add any view element here on which you want to apply font if (view instanceof EditText) { ((EditText) view).setTypeface(font.ROBO_LIGHT); } if (view instanceof TextView) { ((TextView) view).setTypeface(font.ROBO_LIGHT); } else if (view instanceof ViewGroup && ((ViewGroup) view).getChildCount() > 0) { apply((ViewGroup) view); } } } } 

在上面的代码中,我仅在textView和EditText上应用了字体,您也可以同样在其他视图元素上应用字体。您只需将根视图组的ID传递给上述应用字体方法即可。 例如你的布局是:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:id="@+id/mainParent" tools:context="${relativePackage}.${activityClass}" > <RelativeLayout android:id="@+id/mainContainer" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_above="@+id/homeFooter" android:layout_below="@+id/edit" > <ImageView android:id="@+id/PreviewImg" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/abc_list_longpressed_holo" android:visibility="gone" /> <RelativeLayout android:id="@+id/visibilityLayer" android:layout_width="match_parent" android:layout_height="fill_parent" > <ImageView android:id="@+id/UseCamera" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:src="@drawable/camera" /> <TextView android:id="@+id/tvOR" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/UseCamera" android:layout_centerHorizontal="true" android:layout_marginTop="20dp" android:text="OR" android:textSize="30dp" /> <TextView android:id="@+id/tvAND" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="20dp" android:text="OR" android:textSize="30dp" /> </RelativeLayout> 

在上面的布局中,根父标识是“主要父母”现在可以应用字体

 public class MainActivity extends BaseFragmentActivity { private EditText etName; private EditText etPassword; private TextView tvTitle; public static boolean isHome = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Font font=Font.getInstance(getApplicationContext()); FontHelper.applyFont(findViewById(R.id.mainParent), getApplicationContext()); } } 

干杯:)

我build议扩展TextView,并始终在您的XML布局或任何需要TextView的地方使用自定义的TextView。 在您的自定义TextView中,覆盖setTypeface

 @Override public void setTypeface(Typeface tf, int style) { //to handle bold, you could also handle italic or other styles here as well if (style == 1){ tf = Typeface.createFromAsset(getContext().getApplicationContext().getAssets(), "MuseoSans700.otf"); }else{ tf = Typeface.createFromAsset(getContext().getApplicationContext().getAssets(), "MuseoSans500.otf"); } super.setTypeface(tf, 0); } 

从Android O开始,现在可以直接从XML中定义,而且我的bug现在已经closures了!

详情请看这里

TL; DR:

首先,您必须将字体添加到项目中

其次你添加一个字体系列,就像这样:

 <?xml version="1.0" encoding="utf-8"?> <font-family xmlns:android="http://schemas.android.com/apk/res/android"> <font android:fontStyle="normal" android:fontWeight="400" android:font="@font/lobster_regular" /> <font android:fontStyle="italic" android:fontWeight="400" android:font="@font/lobster_italic" /> </font-family> 

最后,您可以使用布局或样式中的字体:

 <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:fontFamily="@font/lobster"/> <style name="customfontstyle" parent="@android:style/TextAppearance.Small"> <item name="android:fontFamily">@font/lobster</item> </style> 

请享用!

汤姆的解决scheme很好,但只适用于TextView和EditText。

如果你想覆盖大部分的视图(RadioGroup,TextView,Checkbox …),我创build了一个方法:

 protected void changeChildrenFont(ViewGroup v, Typeface font){ for(int i = 0; i < v.getChildCount(); i++){ // For the ViewGroup, we'll have to use recursivity if(v.getChildAt(i) instanceof ViewGroup){ changeChildrenFont((ViewGroup) v.getChildAt(i), font); } else{ try { Object[] nullArgs = null; //Test wether setTypeface and getTypeface methods exists Method methodTypeFace = v.getChildAt(i).getClass().getMethod("setTypeface", new Class[] {Typeface.class, Integer.TYPE}); //With getTypefaca we'll get back the style (Bold, Italic...) set in XML Method methodGetTypeFace = v.getChildAt(i).getClass().getMethod("getTypeface", new Class[] {}); Typeface typeFace = ((Typeface)methodGetTypeFace.invoke(v.getChildAt(i), nullArgs)); //Invoke the method and apply the new font with the defined style to the view if the method exists (textview,...) methodTypeFace.invoke(v.getChildAt(i), new Object[] {font, typeFace == null ? 0 : typeFace.getStyle()}); } //Will catch the view with no such methods (listview...) catch (Exception e) { e.printStackTrace(); } } } } 

此方法将取回以XML(粗体,斜体…)设置的视图样式,并在存在的情况下应用它们。

对于ListView,我总是创build一个适配器,并在getView中设置字体。

我为当前视图层次结构中的视图编写了一个类分配字体,并基于当前字体属性(粗体,普通,如果需要,可以添加其他样式):

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

现在,在onViewCreate或onCreateView中的所有片段中,在onCreate中的所有活动中以及getView或newView中的所有视图适配器中,只需调用:

 typefaceAssigner.assignTypeface(view); 

我也想提高weston对API 21 Android 5.0的回答。

使用DEFAULT字体时,我的Samsung s5上出现同样的问题。 (与其他字体工作正常)

我设法通过在XML文件中为每个Textview或Button设置字体 (例如“sans”)来工作

 <TextView android:layout_width="match_parent" android:layout_height="39dp" android:textColor="@color/abs__background_holo_light" android:textSize="12sp" android:gravity="bottom|center" android:typeface="sans" /> 

和MyApplication类中:

 public class MyApplication extends Application { @Override public void onCreate() { TypefaceUtil.overrideFont(getApplicationContext(), "SANS_SERIF", "fonts/my_font.ttf"); } } 

希望它有帮助。

在某些情况下, 此解决scheme无法正常工作。
所以我扩展它:

FontsReplacer.java

 public class MyApplication extends Application { @Override public void onCreate() { FontsReplacer.replaceFonts(this); super.onCreate(); } } 

https://gist.github.com/orwir/6df839e3527647adc2d56bfadfaad805

书法作品相当好,但它不适合我,因为它不支持字体家族的不同粗细(粗体,斜体等)。

所以我尝试了Fontain ,它允许您定义自定义视图并将其应用于自定义字体系列。

为了使用Fontain,你应该添加以下内容到你的应用模块build.gradle:

 compile 'com.scopely:fontain:1.0.0' 

然后,而不是使用常规的TextView,您应该使用FontTextView

带有大写和粗体内容的FontTextView示例:

  <com.scopely.fontain.views.FontTextView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/black" android:textColor="@android:color/white" android:textSize="11dp" android:gravity="center" android:id="@+id/tv1" app:font_family="myCustomFont" app:caps_mode="characters" app:font_weight="BOLD"/> 
 package com.theeasylearn.demo.designdemo; import android.content.Context; import android.graphics.Typeface; import android.util.AttributeSet; import android.widget.TextView; public class MyButton extends TextView { public MyButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public MyButton(Context context, AttributeSet attrs) { super(context, attrs); init(); } public MyButton(Context context) { super(context); init(); } private void init() { Typeface tf = Typeface.createFromAsset( getContext().getAssets(), "angelina.TTF"); setTypeface(tf); } } 

是的,可以将字体设置为整个应用程序。

最简单的方法是将所需字体打包到您的应用程序中。

为此,只需在项目根目录下创build资产/文件夹,然后将字体(以TrueType或TTF格式)放入资产中。

例如,您可能会创build资产/字体/并将TTF文件放在那里。

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