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

我在我的应用程序中使用Roboto light字体。要设置字体,我必须将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>
345439 次浏览

阅读下面的更新

我有嵌入一个新的字体同样的问题,最后得到它与扩展TextView和设置字体内部的工作。

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。是唯一对我有用的东西…

更新

现在,我使用反射改变字体在整个应用程序没有扩展TextViews。看看这篇SO帖子

更新2

从API级别26开始,可以在“支持库”中使用

android:fontFamily="@font/embeddedfont"

进一步信息:XML字体

答案是否定的,你不能。 看到是否可以为整个应用程序设置自定义字体? 获取更多信息。< / p >

这里有一些变通办法,但没有像“这里的一行代码和我所有的字体将是而不是”那样的行。

(我有点感谢谷歌和苹果公司)。自定义字体有一个地方,但使它们容易取代整个应用程序,将创建一个Comic Sans应用程序的整个世界)

答案是肯定的。

TextViewButton类的Global Roboto light:

<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中选择你想要的样式,然后基于原始样式创建你的自定义样式。最后,应用样式作为应用程序的主题。

<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必须包含它。

为整个应用程序这样做的另一种方法是使用基于回答的反射

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及以上的早期版本,检查完整的示例

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

  • 选项1:应用反射来更改系统字体
  • 选项2:为每个需要自定义字体的视图创建并子类化自定义视图类
  • 实现一个遍历视图的视图爬虫 当前屏幕的层次
  • 选项4:使用第三方库。

这些选项的详细信息可以在在这里中找到。

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

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

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

我知道这个问题很老了,但我已经找到了一个很好的解决方案。 基本上,你传递一个容器布局给这个函数,它会将字体应用到所有支持的视图,并在子布局中递归循环:

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的字体设置为normalsansserifmonospace(不是自定义字体!),你就可以这样做。

定义一个主题,并将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 reference

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

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

只需使用这个库编译在你的成绩文件

complie'me.anwarshahriar:calligrapher:1.0'

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

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

这是最优雅快捷的方法。

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

    如果你有支持库>=,签入你的应用程序build.gradle 李26.0.0 < /强> < / >
  1. 将“字体”文件夹添加到资源文件夹中,并在那里添加字体
  2. 在你的应用程序主样式中引用默认字体族:

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

Check https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html for more detailed information.

这是为我的项目工作,源https://gist.github.com/artem-zinnatullin/7749076

在资产文件夹内创建字体目录,然后复制您的自定义字体到字体目录,例如我使用trebuchet.ttf;

创建一个类TypefaceUtil.java;

import android.content.Context;
import android.graphics.Typeface;
import android.util.Log;


import java.lang.reflect.Field;
public class TypefaceUtil {


public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) {
try {
final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);


final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
defaultFontTypefaceField.setAccessible(true);
defaultFontTypefaceField.set(null, customFontTypeface);
} catch (Exception e) {


}
}
}

在styles.xml中编辑主题

<item name="android:typeface">serif</item>

My styles.xml中的示例

<resources>


<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:typeface">serif</item><!-- Add here -->
</style>




<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowFullscreen">true</item>
</style>
</resources>

最后,在Activity或Fragment中onCreate调用TypefaceUtil.java

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TypefaceUtil.overrideFont(getContext(), "SERIF", "fonts/trebuchet.ttf");
}

要改变你的应用字体遵循以下步骤:

  1. res目录中创建一个新目录并命名为font
  2. 插入字体.ttf/。在字体文件夹otf,确保字体名称是小写字母和下划线。
  3. res ->valuesstyles.xml<resources> ->添加你的字体<item name="android:fontFamily">@font/font_name</item>

enter image description here

现在你所有的应用文本都应该是你添加的字体。

将这行代码添加到res/value/styles.xml中

<item name="android:fontFamily">@font/circular_medium</item>

整个样式看起来就像这样

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:fontFamily">@font/circular_medium</item>
</style>

将“circular_medium”更改为您自己的字体名称。

我们是这样做的:

private static void OverrideDefaultFont(string defaultFontNameToOverride, string customFontFileNameInAssets, AssetManager assets)
{
//Load custom Font from File
Typeface customFontTypeface = Typeface.CreateFromAsset(assets, customFontFileNameInAssets);


//Get Fontface.Default Field by reflection
Class typeFaceClass = Class.ForName("android.graphics.Typeface");
Field defaultFontTypefaceField = typeFaceClass.GetField(defaultFontNameToOverride);


defaultFontTypefaceField.Accessible = true;
defaultFontTypefaceField.Set(null, customFontTypeface);
}

这在Android Studio中非常非常简单。

  1. 在这个方法中,你需要验证你的minsdkveriosn。它必须需要minsdkversion >=16

Ex: .

  1. 创建“font"文件夹内"res"文件夹中。在android studio New >文件夹在字体文件夹。

See image: .

  1. 将您的字体文件上传到该字体文件夹。

Ex: .

  1. 在你的style.xml文件中,在“基础应用程序主题”的样式下;加上这条线。

    <item name="android:fontFamily">@font/ubuntubold</item>

Ex: .

< p >更多细节: https://coderog.com/community/threads/how-to-set-default-font-family-for-entire-android-app.72/ < / p >