source - android开发




如何在Android中为整个应用程序设置自定义字体? (8)

Android提供了更简单,最好的解决方案,支持库26+支持API级别14。 XML中的字体 它还支持 字体系列 选项。

按照这些简单的步骤,字体系列将在您的应用程序中应用,没有任何障碍:

  1. res中 创建一个 字体 目录
  2. 将字体文件粘贴到 字体中
  3. 右键单击字体文件夹,然后转到“新建”>“字体资源文件”。 将出现“新建资源文件”窗口。
  4. 添加以下属性
<?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>
  1. 在上面的xml文件中。 仅使用 app 来使用支持库。 否则,如果您的应用针对API级别26+,则可以使用 Android
  2. 现在转到您的styles.xml并在主要样式中添加以下行。
    <item name="android:fontFamily">@font/opensans</item>
  3. 要点:仅在使用支持库时才使用 AppCompatActivity
  4. 或者使用以下命令以编程方式设置字体

    view.setTypeface(ResourcesCompat.getFont(context, R.font.opensans));

是否可以在Android应用程序中设置自定义字体?

我尝试了 here 发布的内容,但我不知道我的 extends Application 类在哪里...

有帮助吗?

编辑:

我尝试了以下方法:

  • 添加资源文件夹并在其中插入字体,如下所示:

  • 添加一个从 Application 扩展的新类

  • 从我的 AndroidManifest.xml 调用这个新类。

  • 我按照我的风格添加了它。

MyApp.java:

public class MyApp extends Application {
  @Override
  public void onCreate() {
     super.onCreate();
    FontsOverride.setDefaultFont(this, "DEFAULT", "raleway_regular.ttf");
    //  This FontsOverride comes from the example I posted above
  }
  }

AndroidManifest.xml中:

<application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:supportsRtl="true"
      android:name=".MyApp"
      android:theme="@style/AppTheme">
     ....

styles.xml:

 <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:fontFamily">default</item>
 </style>

但我的字体仍然没有变换......任何想法?

然后调用 MyApp 类。 但对我的字体没有影响......

EDIT2: 我意识到在为按钮设置自定义样式后,我的按钮会应用自定义字体。 这是我的自定义按钮样式:

<style name="MyButtonStyle" parent="Widget.AppCompat.Button">
    <item name="textAllCaps">false</item>
    <item name="android:textAllCaps">false</item>
</style>

以下是它现在的样子:

所以:我的按钮是应用样式,而不是 TextView 。 有关为什么我的自定义字体没有应用于应用程序中的所有项目的任何想法?


kotlin的解决方法就是这样

解决方案的要点 https://gist.github.com/Johnyoat/040ca5224071d01b3f3dfc6cd4d026f7

第一步

将字体文件放在assets / fonts / your_font_file.ttf下并创建一个名为TypeFaceUtil的kotlin类

   class TypefaceUtil{

    fun overridefonts(context: Context, defaultFontToOverride:String, customFontFileNameInAssets:String){
        try {
            val customTypeface = Typeface.createFromAsset(context.assets,customFontFileNameInAssets)
            val defaultTypefaceField = Typeface::class.java.getDeclaredField(defaultFontToOverride)
            defaultTypefaceField.isAccessible = true
            defaultTypefaceField.set(null,customTypeface)
        }catch (e:Exception){
            Timber.e("Cannot set font $customFontFileNameInAssets instead of $defaultFontToOverride")
        }
    }
}

第二步 然后在你的 onCreate

val typefaceUtil = TypefaceUtil()

typefaceUtil.overridefonts(this,"SERIF","fonts/font_file.ttf")

第三步

将此添加到您的风格

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

在android中有一个很棒的自定义字体库:书法
以下是如何使用它的示例。

在Gradle中,您需要将此行放入应用程序的build.gradle文件中:

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

然后创建一个扩展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()
                );
            }
        } 

您应该在资产上创建一个“新目录”“字体”(见下文),因此在该代码中“您的字体路径”应为“fonts / SourceSansPro-Regular.ttf”。 (它只是“字体......”而不是“/ fonts ..”或“assets ..”)

并且在activity类中将此方法放在onCreate之前:

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

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

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

它会将整个活动改为你的字体! 它简单而干净!

在资产上,您应该右键单击“新建目录”,将其命名为“fonts”。 在finder中放入 .ttf 字体文件。

也不要忘记在attrs.xml中添加以下两行,如果你没有attrs.xml文件,在values.xml中创建新文件

 <attr format="string" name="fontPath"/> 
    <item name="calligraphy_tag_id" type="id"/>

在其中的main folder.add fonts文件夹中创建资源文件夹。 在fonts文件夹中添加.ttf文件。

在您的应用主题中添加以下内容

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

将类创建为TypefaceUtil

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

import java.lang.reflect.Field;

public class TypefaceUtil {

    /**
     * Using reflection to override default typeface
     * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE OVERRIDDEN
     * @param context to work with assets
     * @param defaultFontNameToOverride for example "monospace"
     * @param customFontFileNameInAssets file name of the font from assets
     */
    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) {
            Log.e("Can not set","Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride);
        }
    }
}

在应用程序类或Launcher活动中调用它

        TypefaceUtil.overrideFont(getApplicationContext(), "fonts/roboto_regular.ttf", "fonts/roboto_regular.ttf"); // font from assets: "assets/fonts/Roboto-Regular.ttf

如果你按照第一个主题,这应该工作: Here

是的反思。 这是有效的( 根据这个答案 ):

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

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>

尝试下面的代码,它适用于我,希望它也会帮助你。

public class BaseActivity extends AppCompatActivity {

private Typeface typeace;
@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    typeace = Typeface.createFromAsset(getAssets(), getResources().getString(R.string.font_name));
}

@Override
protected void onStart() {
    // TODO Auto-generated method stub
    super.onStart();
    overrideFonts(this,getWindow().getDecorView());
}

private void overrideFonts(final Context context, final View v) {
    try {
        if (v instanceof ViewGroup) {
            ViewGroup vg = (ViewGroup) v;
            for (int i = 0; i < vg.getChildCount(); i++) {
                View child = vg.getChildAt(i);
                overrideFonts(context, child);
         }
        } else if (v instanceof TextView) {
            ((TextView) v).setTypeface(typeace);
        } else if (v instanceof EditText ) {
            ((EditText) v).setTypeface(typeace);
        } else if (v instanceof Button) {
            ((Button) v).setTypeface(typeace);
        }
    } catch (Exception e) {
 }
 }
}

现在将此BaseActivity扩展到您的任何Activity,或者如果您正在使用,您可以为片段创建相同的类。

注意: - 如果要将某些视图设置为不同的字体,则必须按以下方式以编程方式设置

private Typeface typeface;
typeface = Typeface.createFromAsset(getAssets(), getResources().getString(R.string.font_name_bold));
tvUserName.setTypeface(typeface);

所以试一试让我知道,如果我能帮助你更进一步


我也尝试过字体覆盖,但最后它不是一个可靠的解决方案,遗憾的是覆盖字体需要更多。 您可以等待带有自定义字体的Android O出来或使用第三方库。

我遇到的最后一个解决方案是这个库 Caligraphy ,它很容易启动,让你可以使用 Caligraphy 字体。 在检查其源代码的同时,我理解为什么只是覆盖字体不起作用,所以即使你不打算使用它我也建议一次阅读它。

祝好运


我所做的只是:

1:在RES文件夹中添加“新资源目录”,从下拉列表中选择RESOURCE TYPE作为“font”,命名为新目录“font”并保存。

2:将我的“custom_font.ttf”添加到刚刚创建的FONT文件夹中。

3:在STYLES.XML的应用程序基础主题中添加了我的自定义字体

DONE。







android