如何为整个Android应用程序设置默认字体系列

我在我的应用程序中使用Roboto光字体。 要设置字体,我已经将android:fontFamily="sans-serif-light"到每个视图。 有没有办法将Roboto字体声明为默认字体族到整个应用程序? 我已经尝试过,但似乎没有工作。

 <style name="AppBaseTheme" parent="android:Theme.Light"></style> <style name="AppTheme" parent="AppBaseTheme"> <item name="android:fontFamily">sans-serif-light</item> </style> 

答案是肯定的。

用于TextViewButton类的全局Roboto灯光:

 <style name="AppTheme" parent="AppBaseTheme"> <item name="android:textViewStyle">@style/RobotoTextViewStyle</item> <item name="android:buttonStyle">@style/RobotoButtonStyle</item> </style> <style name="RobotoTextViewStyle" parent="android:Widget.TextView"> <item name="android:fontFamily">sans-serif-light</item> </style> <style name="RobotoButtonStyle" parent="android:Widget.Holo.Button"> <item name="android:fontFamily">sans-serif-light</item> </style> 

只需从列表themes.xml中select所需的样式,然后根据原始样式创build自定义样式。 最后,将风格作为应用程序的主题。

 <application android:theme="@style/AppTheme" > </application> 

它只能使用像Roboto这样的内置字体,但这是个问题。 对于自定义字体(例如从资产中加载),此方法将不起作用。

编辑08/13/15

如果您使用AppCompat主题,请记住删除android:前缀。 例如:

 <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="android:textViewStyle">@style/RobotoTextViewStyle</item> <item name="buttonStyle">@style/RobotoButtonStyle</item> </style> 

注意buttonStyle不包含android:前缀,但是textViewStyle必须包含它。

您可以使用书法pipe理与Android的字体

https://github.com/chrisjenx/Calligraphy

使用这个从资产的embeddedCUTSOM字体

我有同样的问题embedded一个新的字体,最后得到它与扩展TextView和设置typefont里面。

 public class YourTextView extends TextView { public YourTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public YourTextView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public YourTextView(Context context) { super(context); init(); } private void init() { Typeface tf = Typeface.createFromAsset(context.getAssets(), "fonts/helveticaneue.ttf"); setTypeface(tf); } } 

您必须稍后将TextView元素更改为在每个元素中。 如果您在Eclipse中使用UI-Creator,有时候他不会显示TextViews。 是唯一对我有用的东西

UPDATE

现在,我正在使用reflection来改变整个应用程序中的字体,而无需扩展TextViews。 看看这个SOpost

随着Android Oreo的发布,您可以使用支持库来实现这一目标。

  1. 检查你的应用程序build.gradle,如果你有支持库> = 26.0.0
  2. 添加“ 字体 ”文件夹到您的资源文件夹,并在那里添加您的字体
  3. 引用您的应用程序主风格的默认字体系列:

     <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:fontFamily">@font/your_font</item> <item name="fontFamily">@font/your_font</item> <!-- target android sdk versions < 26 and > 14 if theme other than AppCompat --> </style> 

查看https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html获取更多详细信息。;

不谈性能,对于自定义字体,如果它是一个TextView,你可以有一个循环遍历所有视图和设置字体的recursion方法:

 public class Font { public static void setAllTextView(ViewGroup parent) { for (int i = parent.getChildCount() - 1; i >= 0; i--) { final View child = parent.getChildAt(i); if (child instanceof ViewGroup) { setAllTextView((ViewGroup) child); } else if (child instanceof TextView) { ((TextView) child).setTypeface(getFont()); } } } public static Typeface getFont() { return Typeface.createFromAsset(YourApplicationContext.getInstance().getAssets(), "fonts/whateverfont.ttf"); } } 

在您的所有活动中,在setContentView之后将当前的ViewGroup传递给它并完成:

 ViewGroup group = (ViewGroup) getWindow().getDecorView().findViewById(android.R.id.content); Font.setAllTextView(group); 

对于片段,你可以做类似的事情。

为整个应用程序做这个的另一种方法是使用基于这个答案的reflection

 public class TypefaceUtil { /** * Using reflection to override default typefaces * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE * OVERRIDDEN * * @param typefaces map of fonts to replace */ public static void overrideFonts(Map<String, Typeface> typefaces) { 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", "Can not set custom fonts"); } } public static Typeface getTypeface(int fontType, Context context) { // here you can load the Typeface from asset or use default ones switch (fontType) { case BOLD: return Typeface.create(SANS_SERIF, Typeface.BOLD); case ITALIC: return Typeface.create(SANS_SERIF, Typeface.ITALIC); case BOLD_ITALIC: return Typeface.create(SANS_SERIF, Typeface.BOLD_ITALIC); case LIGHT: return Typeface.create(SANS_SERIF_LIGHT, Typeface.NORMAL); case CONDENSED: return Typeface.create(SANS_SERIF_CONDENSED, Typeface.NORMAL); case THIN: return Typeface.create(SANS_SERIF_MEDIUM, Typeface.NORMAL); case MEDIUM: return Typeface.create(SANS_SERIF_THIN, Typeface.NORMAL); case REGULAR: default: return Typeface.create(SANS_SERIF, Typeface.NORMAL); } } } 

那么只要你想覆盖字体,你可以调用方法,并给它一个字体的地图,如下所示:

 Typeface regular = TypefaceUtil.getTypeface(REGULAR, context); Typeface light = TypefaceUtil.getTypeface(REGULAR, context); Typeface condensed = TypefaceUtil.getTypeface(CONDENSED, context); Typeface thin = TypefaceUtil.getTypeface(THIN, context); Typeface medium = TypefaceUtil.getTypeface(MEDIUM, context); Map<String, Typeface> fonts = new HashMap<>(); fonts.put("sans-serif", regular); fonts.put("sans-serif-light", light); fonts.put("sans-serif-condensed", condensed); fonts.put("sans-serif-thin", thin); fonts.put("sans-serif-medium", medium); TypefaceUtil.overrideFonts(fonts); 

为完整的示例检查

这只适用于早期版本的Android SDK 21及更高版本检查完整的示例

只需使用这个lib在你的档案文件中编译它

 complie'me.anwarshahriar:calligrapher:1.0' 

并在主要活动的onCreate方法中使用它

 Calligrapher calligrapher = new Calligrapher(this); calligrapher.setFont(this, "yourCustomFontHere.ttf", true); 

这是最优雅的超快捷方式。

Android并没有提供很多支持在整个应用程序中应用字体的方法(请参阅此问题 )。 你有4个选项来设置整个应用程序的字体:

  • 选项1:应用reflection来更改系统字体
  • 选项2:为每个需要自定义字体的视图创build子类自定义视图类
  • 选项3:实现遍历当前屏幕的视图层次结构的视图爬行器
  • 选项4:使用第三方库。

这些选项的细节可以在这里find。

我知道这个问题是相当古老的,但我find了一个很好的解决scheme。 基本上,你将一个容器布局传递给这个函数,它将把字体应用到所有支持的视图,并recursion地在子布局中注册:

 public static void setFont(ViewGroup layout) { final int childcount = layout.getChildCount(); for (int i = 0; i < childcount; i++) { // Get the view View v = layout.getChildAt(i); // Apply the font to a possible TextView try { ((TextView) v).setTypeface(MY_CUSTOM_FONT); continue; } catch (Exception e) { } // Apply the font to a possible EditText try { ((TextView) v).setTypeface(MY_CUSTOM_FONT); continue; } catch (Exception e) { } // Recursively cicle into a possible child layout try { ViewGroup vg = (ViewGroup) v; Utility.setFont(vg); continue; } catch (Exception e) { } } } 

仅仅将app的字体设置为normalsansserif或者monospace (而不是自定义字体!),你可以这样做。

定义一个主题,并将android:typeface属性设置为要在styles.xml使用的字体:

 <resources> <!-- custom normal activity theme --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <!-- other elements --> <item name="android:typeface">monospace</item> </style> </resources> 

将主题应用于AndroidManifest.xml文件中的整个应用程序:

 <?xml version="1.0" encoding="utf-8"?> <manifest ... > <application android:theme="@style/AppTheme" > </application> </manifest> 

android引用

试试这个库,它的轻量级和易于实现

https://github.com/sunnag7/FontStyler

 <com.sunnag.fontstyler.FontStylerView android:textStyle="bold" android:text="@string/about_us" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingTop="8dp" app:fontName="Lato-Bold" android:textSize="18sp" android:id="@+id/textView64" /> 

答案是否定的,你不能。 请参阅是否可以为整个应用程序设置自定义字体? 了解更多信息。

有一些解决方法,但是“这里的一行代码和所有的字体都不是这个 ”。

(我感谢Google和Apple)。 自定义字体有一个地方,但使它们很容易地取代应用程序的范围,将创build一个漫画的应用程序的整个世界)