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

如何为整个Android应用程序设置默认字体系列,android,android-fonts,Android,Android Fonts,我在应用程序中使用Roboto light字体。要设置字体,我必须在每个视图中添加android:fontfamine=“sans serif light”。有没有办法将Roboto字体声明为整个应用程序的默认字体系列?我试过这样做,但似乎不起作用 <style name="AppBaseTheme" parent="android:Theme.Light"></style> <style name="AppTheme" parent="AppBaseTheme"

我在应用程序中使用Roboto light字体。要设置字体,我必须在每个视图中添加
android:fontfamine=“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>

无衬线灯

阅读下面的更新

我在嵌入一种新字体时遇到了同样的问题,最后让它扩展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创建者,有时他不会正确显示文本视图。是唯一对我有用的东西

更新

现在我使用反射来改变整个应用程序中的字体,而不扩展文本视图

更新2

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

android:fontFamily="@font/embeddedfont"

进一步信息:

答案是不,你不能。 看见 了解更多信息

这里有一些变通办法,但“这里只有一行代码,我所有的字体都是这个而不是那个”这几行中没有任何内容

(为此,我有点感谢谷歌和苹果)。自定义字体有其一席之地,但如果能在整个应用程序范围内轻松替换它们,就会创造出一个应用程序的世界)

答案是肯定的

用于
文本视图
按钮
类的全局机器人灯:

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

请注意,
按钮样式
不包含
android:
前缀,但
文本视图样式
必须包含前缀。

另一种对整个应用程序执行此操作的方法是使用基于此的反射

公共类TypefaceUtil{
/**
*使用反射覆盖默认字体
*注意:不要忘记将应用程序主题的字体设置为默认字体,这将是
*凌驾
*
*@param typefaces要替换的字体映射
*/
公共静态无效覆盖(地图字体){
试一试{
最终字段=Typeface.class.getDeclaredField(“sSystemFontMap”);
字段。setAccessible(true);
MapoldFonts=(映射)字段.get(null);
如果(旧字体!=null){
oldFonts.putAll(字体);
}否则{
旧字体=字体;
}
field.set(空,旧字体);
字段.setAccessible(false);
}捕获(例外e){
Log.e(“TypefaceUtil”,“无法设置自定义字体”);
}
}
公共静态字体getTypeface(int-fontType,上下文){
//在这里,您可以从资源加载字体或使用默认字体
开关(fontType){
粗体字:
返回Typeface.create(SANS_SERIF,Typeface.BOLD);
斜体字:
返回Typeface.create(SANS_SERIF,Typeface.ITALIC);
大小写粗体(斜体):
返回字体。创建(无衬线,字体。粗体\斜体);
箱灯:
返回字体。创建(无衬线光,字体。普通);
案例压缩:
返回Typeface.create(SANS\u SERIF\u CONDENSED,Typeface.NORMAL);
薄型:
返回Typeface.create(SANS_SERIF_MEDIUM,Typeface.NORMAL);
病例培养基:
返回Typeface.create(SANS_SERIF_THIN,Typeface.NORMAL);
常规病例:
违约:
返回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);
Typeface regular=TypefaceUtil.getTypeface(regular,context);
Typeface light=TypefaceUtil.getTypeface(常规,上下文);
Typeface condensed=TypefaceUtil.getTypeface(condensed,context);
Typeface thin=TypefaceUtil.getTypeface(thin,上下文);
Typeface medium=TypefaceUtil.getTypeface(medium,context);
映射字体=新建HashMap();
字体。放置(“无衬线”,常规);
字体。放置(“无衬线灯”,灯);
字体。放置(“无衬线压缩”,压缩);
字体。放置(“无衬线细”,细);
字体。放置(“无衬线中”,中);
TypefaceUtil.overrideFonts(字体);
举个例子


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

Android没有为在整个应用程序中应用字体提供太多支持(参见此)。您有4个选项可设置整个应用程序的字体:

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

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

不要谈论性能,对于自定义字体,您可以在所有视图中使用递归方法循环,如果是文本视图,则可以设置字体:

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 group = (ViewGroup) getWindow().getDecorView().findViewById(android.R.id.content);
Font.setAllTextView(group);

对于fragment,您可以做类似的事情。

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

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) { }
    }
}
publicstaticvoidsetfont(视图组布局)
{
final int childcount=layout.getChildCount();
for(int i=0;ipublic 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");
    }
}
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) { }
    }
}
<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>
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application
        android:theme="@style/AppTheme" >
    </application>
</manifest>
<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'
Calligrapher calligrapher = new Calligrapher(this);
calligrapher.setFont(this, "yourCustomFontHere.ttf", true);
<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>
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) {

        }
    }
}
<item name="android:typeface">serif</item>
<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>
@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TypefaceUtil.overrideFont(getContext(), "SERIF", "fonts/trebuchet.ttf");
    }
<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>
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);
}