在安卓主题中添加自定义字体

45

有没有办法在Android主题中添加自定义字体?

我已经阅读了快速提示:自定义Android字体,但是在这里我们必须通过编程的方式将自定义字体添加到文本。

TextView txt = (TextView) findViewById(R.id.custom_font);  
Typeface font = Typeface.createFromAsset(getAssets(), "Chantelli_Antiqua.ttf");  
txt.setTypeface(font); 

但我想通过样式/主题设置自定义字体。

6个回答

22
很遗憾,Android没有提供一种快速、简单、干净的方法来更改您整个应用程序的字体。但是我最近研究了这个问题并创建了一些工具,可以让您在不编写任何代码的情况下更改字体(您可以通过xml、样式甚至文本外观来完成所有操作)。它们基于类似其他答案中看到的解决方案,但允许更大的灵活性。您可以在此博客上阅读有关其所有信息,并在此处查看github项目。

以下是如何应用这些工具的示例。将所有字体文件放在assets/fonts/中。然后,在一个xml文件中声明这些字体(例如res/xml/fonts.xml),并在应用程序早期使用TypefaceManager.initialize(this, R.xml.fonts);加载此文件(例如,在Application类的onCreate中)。xml文件如下所示:

<?xml version="1.0" encoding="utf-8"?>
<familyset>

    <!-- Some Font. Can be referenced with 'someFont' or 'aspergit' -->
    <family>
        <nameset>
            <name>aspergit</name>
            <name>someFont</name>
        </nameset>
        <fileset>
            <file>Aspergit.ttf</file>
            <file>Aspergit Bold.ttf</file>
            <file>Aspergit Italic.ttf</file>
            <file>Aspergit Bold Italic.ttf</file>
        </fileset>
    </family>

    <!-- Another Font. Can be referenced with 'anotherFont' or 'bodoni' -->
    <family>
        <nameset>
            <name>bodoni</name>
            <name>anotherFont</name>
        </nameset>
        <fileset>
            <file>BodoniFLF-Roman.ttf</file>
            <file>BodoniFLF-Bold.ttf</file>
        </fileset>
    </family>

</familyset>

现在你可以在样式或xml中使用这些字体(前提是你使用了我上面提到的工具),通过在自定义TextView com.innovattic.font.FontTextView 中设置flFont属性来实现。下面你可以看到如何通过编辑res/values/styles.xml,将字体应用到整个应用程序中的所有文本:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">

    <!-- Application theme -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
        <item name="android:textViewStyle">@style/MyTextViewStyle</item>
    </style>

    <!-- Style to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextViewStyle" parent="@android:style/Widget.Holo.Light.TextView">
        <item name="android:textAppearance">@style/MyTextAppearance</item>
    </style>

    <!-- Text appearance to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextAppearance" parent="@android:style/TextAppearance.Holo">
        <!-- Alternatively, reference this font with the name "aspergit" -->
        <!-- Note that only our own TextView's will use the font attribute -->
        <item name="flFont">someFont</item>
        <item name="android:textStyle">bold|italic</item>
    </style>

    <!-- Alternative style, maybe for some other widget -->
    <style name="StylishFont">
        <item name="flFont">anotherFont</item>
        <item name="android:textStyle">normal</item>
    </style>

</resources>

伴随着res/layout/layout.xml的附带内容:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <!-- This text view is styled with the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This uses my font in bold italic style" />

    <!-- This text view is styled here and overrides the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:flFont="anotherFont"
        android:textStyle="normal"
        android:text="This uses another font in normal style" />

    <!-- This text view is styled with a style and overrides the app theme -->
    <com.innovattic.font.FontTextView
        style="@style/StylishFont"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This also uses another font in normal style" />

</LinearLayout>

不要忘记在您的Android清单中应用主题。


由于您也在使用Java代码,因此我们可以以更简单的方式完成它。 - Lavekush Agrawal
这应该成为 Android 的本地功能。 - Zach

12

我认为这是这个问题这个问题的重复。

在运行时,我的活动中使用类似于以下内容:

FontUtils.setCustomFont(findViewById(R.id.top_view), getAssets());

在XML中:

        <TextView
            android:id="@+id/my_label"
            android:tag="condensed"
            android:text="@string/label"
            ... />

理论上你可以创建样式,并将其与FontUtils / 运行时代码一起使用。

<style name="roboto_condensed">
    <item name="android:tag">condensed,your-own-css-like-language-here</item>
</style>

FontUtils类:

public class FontUtils {
  private static Typeface normal;

  private static Typeface bold;

  private static Typeface condensed;

  private static Typeface light;

  private static void processsViewGroup(ViewGroup v, final int len) {

    for (int i = 0; i < len; i++) {
      final View c = v.getChildAt(i);
      if (c instanceof TextView) {
        setCustomFont((TextView) c);
      } else if (c instanceof ViewGroup) {
        setCustomFont((ViewGroup) c);
      }
    }
  }

  private static void setCustomFont(TextView c) {
    Object tag = c.getTag();
    if (tag instanceof String) {
      if (((String) tag).contains("bold")) {
        c.setTypeface(bold);
        return;
      }
      if (((String) tag).contains("condensed")) {
        c.setTypeface(condensed);
        return;
      }
      if (((String) tag).contains("light")) {
        c.setTypeface(light);
        return;
      }
    }
    c.setTypeface(normal);
  }

  public static void setCustomFont(View topView, AssetManager assetsManager) {
    if (normal == null || bold == null || condensed == null || light == null) {
      normal = Typeface.createFromAsset(assetsManager, "fonts/roboto/Roboto-Regular.ttf");
      bold = Typeface.createFromAsset(assetsManager, "fonts/roboto/Roboto-Bold.ttf");
      condensed = Typeface.createFromAsset(assetsManager, "fonts/roboto/Roboto-Condensed.ttf");
      light = Typeface.createFromAsset(assetsManager, "fonts/roboto/Roboto-Light.ttf");
    }

    if (topView instanceof ViewGroup) {
      setCustomFont((ViewGroup) topView);
    } else if (topView instanceof TextView) {
      setCustomFont((TextView) topView);
    }
  }

  private static void setCustomFont(ViewGroup v) {
    final int len = v.getChildCount();
    processsViewGroup(v, len);
  }
}

4
通过使用我的CustomTextView,您可以直接在XML布局文件中指定assets文件夹中的字体文件名。

我的答案在这里


3
你可以将自定义的字体类型放在 assets 文件夹中,并从那里检索它。
声明 Typefaces 如下:
Typeface helveticaBold;
Typeface helveticaRegular;

在onCreate()方法中编写以下代码:

helveticaBold = Typeface.createFromAsset(getAssets(), "helvetica_bold.ttf");
helveticaRegular = Typeface.createFromAsset(getAssets(), "helvetica_regular.ttf");

最后,将TextView或EditText的文本字体设置为:
editText.setTypeface(helveticaRegular);

这就是全部内容...


0

我认为你的问题的答案是使用自定义TextView并添加额外的XML参数,然后将其包含到你的主题中。

你可以在TextView(Context context, AttributeSet attrs)构造函数中解析这个值来进行初始化。请查看this链接,了解如何为你的视图定义自定义属性并对其进行初始化的示例。


-1
我希望这就是你想要的,但即使不是,它也应该是其他人的一个很好的参考。

** 注意:字体可以在计算机/本地磁盘(C:)/Windows/Fonts中找到 **

复制你想要在上面使用的字体,并将其粘贴到Eclipse中资产文件夹中新创建的文件夹中的Fonts文件夹中。

    private void initTypeFace()
    {
        TypeFace tf = TypeFace.createFromAsset(getAsset(),
                      "Chantelli Antiqua.ttf");

        TextView txt = (TextView) findViewById(R.id.custom_font);

        txt.setTypeface(tf);
        example_button1.setTypeface(tf);
        example_button2.setTypeface(tf);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接