Android - 使用自定义字体

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3651086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 11:10:28  来源:igfitidea点击:

Android - Using Custom Font

androidcustom-fontandroid-fontsandroid-typeface

提问by RATTLESNAKE

I applied a custom font to a TextView, but it doesn't seems to change the typeface.

我将自定义字体应用于 a TextView,但它似乎没有改变字体。

Here is my code:

这是我的代码:

    Typeface myTypeface = Typeface.createFromAsset(getAssets(), "fonts/myFont.ttf");
    TextView myTextView = (TextView)findViewById(R.id.myTextView);
    myTextView.setTypeface(myTypeface);

Can anyone please get me out of this issue?

任何人都可以让我摆脱这个问题吗?

采纳答案by Octavian A. Damiean

On Mobiletuts+ there is very good tutorial on Text formatting for Android. Quick Tip: Customize Android Fonts

在 Mobiletuts+ 上有非常好的 Android 文本格式教程。快速提示:自定义 Android 字体

EDIT: Tested it myself now. Here is the solution. You can use a subfolder called fonts but it must go in the assetsfolder not the resfolder. So

编辑:现在自己测试了。这是解决方案。您可以使用名为 fonts 的子文件夹,但它必须位于assets文件夹而不是res文件夹中。所以

assets/fonts

资产/字体

Also make sure that the font ending I mean the ending of the font file itself is all lower case. In other words it should not be myFont.TTFbut myfont.ttfthis way must be in lower case

还要确保字体结尾我的意思是字体文件本身的结尾都是小写的。换句话说它不应该myFont.TTF但是myfont.ttf这种方式必须是小写

回答by javaxian

After trying most of the solutions described in this thread, I accidentally found Calligraphy (https://github.com/chrisjenx/Calligraphy) - a library by Christopher Jenkins that lets you easily add custom fonts to your app. The advantages of his lib comparing to approaches suggested here are:

在尝试了本主题中描述的大多数解决方案后,我偶然发现了 Calligraphy ( https://github.com/chrisjenx/Calligraphy) - Christopher Jenkins 的一个库,可让您轻松地将自定义字体添加到您的应用程序中。与这里建议的方法相比,他的 lib 的优点是:

  1. you don't have to introduce your own overriden TextView component, you use the built-in TextView
  2. you can easily include the library using gradle
  3. The library doesn't limit your choice of fonts; you just add your preferred ones to the assets dir
  4. you not only get custom text views — all the other text-based Android compontents will also be displayed using your custom font.
  1. 你不必引入你自己的重写 TextView 组件,你使用内置的 TextView
  2. 您可以使用 gradle 轻松包含该库
  3. 该库不限制您对字体的选择;您只需将您喜欢的添加到资产目录中
  4. 您不仅可以获得自定义文本视图——所有其他基于文本的 Android 组件也将使用您的自定义字体显示。

回答by espinchi

I know there are good answers already, but here's a fully working implementation.

我知道已经有很好的答案,但这里有一个完整的实现。

Here's the custom text view:

这是自定义文本视图:

package com.mycompany.myapp.widget;

/**
 * Text view with a custom font.
 * <p/>
 * In the XML, use something like {@code customAttrs:customFont="roboto-thin"}. The list of fonts
 * that are currently supported are defined in the enum {@link CustomFont}. Remember to also add
 * {@code xmlns:customAttrs="http://schemas.android.com/apk/res-auto"} in the header.
 */
public class CustomFontTextView extends TextView {

    private static final String sScheme =
            "http://schemas.android.com/apk/res-auto";
    private static final String sAttribute = "customFont";

    static enum CustomFont {
        ROBOTO_THIN("fonts/Roboto-Thin.ttf"),
        ROBOTO_LIGHT("fonts/Roboto-Light.ttf");

        private final String fileName;

        CustomFont(String fileName) {
            this.fileName = fileName;
        }

        static CustomFont fromString(String fontName) {
            return CustomFont.valueOf(fontName.toUpperCase(Locale.US));
        }

        public Typeface asTypeface(Context context) {
            return Typeface.createFromAsset(context.getAssets(), fileName);
        }
    }

    public CustomFontTextView(Context context, AttributeSet attrs) {
        super(context, attrs);

        if (isInEditMode()) {
            return;
        } else {
            final String fontName = attrs.getAttributeValue(sScheme, sAttribute);

            if (fontName == null) {
                throw new IllegalArgumentException("You must provide \"" + sAttribute + "\" for your text view");
            } else {
                final Typeface customTypeface = CustomFont.fromString(fontName).asTypeface(context);
                setTypeface(customTypeface);
            }
        }
    }
}

Here's the custom attributes. This should go to your res/attrs.xmlfile:

这是自定义属性。这应该转到您的res/attrs.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomFontTextView">
        <attr name="customFont" format="string"/>
    </declare-styleable>
</resources>

And here's how you use it. I'll use a relative layout to wrap it and show the customAttrdeclaration, but it could obviously be whatever layout you already have.

这就是你如何使用它。我将使用相对布局来包装它并显示customAttr声明,但它显然可以是您已经拥有的任何布局。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:customAttrs="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.mycompany.myapp.widget.CustomFontTextView
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="foobar"
         customAttrs:customFont="roboto_thin" />

</RelativeLayout>

回答by benvd

I've successfully used this before. The only difference between our implementations is that I wasn't using a subfolder in assets. Not sure if that will change anything, though.

我以前成功地使用过这个。我们的实现之间的唯一区别是我没有在资产中使用子文件夹。不过,不确定这是否会改变任何事情。

回答by Jelle Fresen

Provided that you placed the font in the right place and there is no error in the font file itself, your code should work like that, RATTLESNAKE.

如果您将字体放置在正确的位置并且字体文件本身没有错误,您的代码应该像 RATTLESNAKE 那样工作。

However, it would be a lot easier if you could just define a font in your layout xml, like this:

但是,如果您可以在布局 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>

With the accompanying res/values/styles.xml:

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

I created a couple of tools specifically for this purpose. Refer to this projectfrom GitHub, or take a look at this blog postwhich explains the whole thing.

我为此专门创建了几个工具。请参阅GitHub 上的这个项目,或查看解释整个事情的这篇博文

回答by jeevan s

The best way to do it From Android O preview release is this way:

It works only if you have android studio-2.4 or above

从 Android O 预览版开始,最好的方法是这样的:它仅在您拥有 android studio-2.4 或更高版本

时才有效

  1. Right-click the res folderand go to New > Android resource directory. The New
    Resource Directory window appears.
  2. In the Resource type list, select font, and then click OK.
  3. Add your font files in the font folder.The folder structure below generates R.font.dancing_script, R.font.la_la, and R.font.ba_ba.
  4. Double-clicka font file to preview the file's fonts in the editor.
  1. 右键单击res 文件夹并转到New > Android resource directory。出现“新建
    资源目录”窗口。
  2. 在资源类型列表中,选择字体,然后单击确定。
  3. 添加您的字体文件中的字体文件夹.The文件夹结构下产生R.font.dancing_scriptR.font.la_laR.font.ba_ba
  4. 双击字体文件可在编辑器中预览文件的字体。

Next we must create a font family:

接下来我们必须创建一个字体系列:

  1. Right-click the font folder and go to New > Font resource file. The New Resource File window appears.
  2. Enter the File Name, and then click OK. The new font resource XML opens in the editor.
  3. Enclose each font file, style, and weight attribute in the font tag element. The following XML illustrates adding font-related attributes in the font resource XML:

  1. 右键单击字体文件夹,然后转到新建 > 字体资源文件。出现“新建资源文件”窗口。
  2. 输入文件名,然后单击确定。新字体资源 XML 在编辑器中打开。
  3. 将每个字体文件、样式和粗细属性括在字体标记元素中。以下 XML 说明在字体资源 XML 中添加与字体相关的属性:

Adding fonts to a TextView:

将字体添加到 TextView:

   <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:fontFamily="@font/hey_fontfamily"/>

As from the documentation

从文档中

Working With Fonts

使用字体

All the steps are correct.

所有步骤都是正确的。

回答by Faakhir

For Custom Fonts in android create a folder within assets folder name it "fonts" place your desired fonts.ttf or .otf file in it.

对于 android 中的自定义字体,在资产文件夹名称中创建一个文件夹“字体”,将您想要的 fonts.ttf 或 .otf 文件放入其中。

If you extends UIBaseFragment:

如果您扩展 UIBaseFragment:

Typeface font = Typeface.createFromAsset(getActivity().getAssets(), "fonts/Arial.ttf");
        tv.setTypeface(font);

else if extends Activity:

否则如果扩展活动:

Typeface font = Typeface.createFromAsset(getContext().getAssets(), "fonts/Arial.ttf");
        tv.setTypeface(font);

回答by guest2343sdfdfs

You can use PixlUI at https://github.com/neopixl/PixlUI

您可以在https://github.com/neopixl/PixlUI使用 PixlUI

import their .jar and use it in XML

导入他们的 .jar 并在 XML 中使用它

 <com.neopixl.pixlui.components.textview.TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world"
    pixlui:typeface="GearedSlab.ttf" />

回答by Miro Kropacek

Since I was not satisfied with all the presented solutions on SO, I've come up with mine. It's based on a little trick with tags (i.e. you can't use tags in your code), I put the font path there. So when defining views, you can do either this:

由于我对 SO 上提出的所有解决方案都不满意,因此我提出了我的解决方案。它基于一个带标签的小技巧(即你不能在你的代码中使用标签),我把字体路径放在那里。因此,在定义视图时,您可以执行以下任一操作:

<TextView
        android:id="@+id/textViewHello1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World 1"
        android:tag="fonts/Oswald-Regular.ttf"/>

or this:

或这个:

<TextView
        android:id="@+id/textViewHello2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World 2"
        style="@style/OswaldTextAppearance"/>

<style name="OswaldTextAppearance">
        <item name="android:tag">fonts/Oswald-Regular.ttf</item>
        <item name="android:textColor">#000000</item>
</style>

Now you can either explicitly access / setup the view as:

现在您可以显式访问/设置视图:

TextView textView = TextViewHelper.setupTextView(this, R.id.textViewHello1).setText("blah");

or just setup everything via:

或者只是通过以下方式设置所有内容:

TextViewHelper.setupTextViews(this, (ViewGroup) findViewById(R.id.parentLayout)); // parentLayout is the root view group (relative layout in my case)

And what is the magic class you ask? Mostly glued from another SO posts, with helper methods for both activity and fragments:

你问的魔法课是什么?主要来自另一个 SO 帖子,带有活动和片段的辅助方法:

import android.app.Activity;
import android.content.Context;
import android.graphics.Typeface;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.HashMap;
import java.util.Map;

public class TextViewHelper {
    private static final Map<String, Typeface> mFontCache = new HashMap<>();

    private static Typeface getTypeface(Context context, String fontPath) {
        Typeface typeface;
        if (mFontCache.containsKey(fontPath)) {
            typeface = mFontCache.get(fontPath);
        } else {
            typeface = Typeface.createFromAsset(context.getAssets(), fontPath);
            mFontCache.put(fontPath, typeface);
        }
        return typeface;
    }

    public static void setupTextViews(Context context, ViewGroup parent) {
        for (int i = parent.getChildCount() - 1; i >= 0; i--) {
            final View child = parent.getChildAt(i);
            if (child instanceof ViewGroup) {
                setupTextViews(context, (ViewGroup) child);
            } else {
                if (child != null) {
                    TextViewHelper.setupTextView(context, child);
                }
            }
        }
    }

    public static void setupTextView(Context context, View view) {
        if (view instanceof TextView) {
            if (view.getTag() != null) // also inherited from TextView's style
            {
                TextView textView = (TextView) view;
                String fontPath = (String) textView.getTag();
                Typeface typeface = getTypeface(context, fontPath);
                if (typeface != null) {
                    textView.setTypeface(typeface);
                }
            }
        }
    }

    public static TextView setupTextView(View rootView, int id) {
        TextView textView = (TextView) rootView.findViewById(id);
        setupTextView(rootView.getContext().getApplicationContext(), textView);
        return textView;
    }

    public static TextView setupTextView(Activity activity, int id) {
        TextView textView = (TextView) activity.findViewById(id);
        setupTextView(activity.getApplicationContext(), textView);
        return textView;
    }
}

回答by Oliver Dixon

Unfortunately there is no good solution for this.

不幸的是,对此没有好的解决方案。

I've seen the many articles about using a custom TextView but what they forget it that it's not only textviews that can implement fonts & there are textviews hidden away in other views inaccessible to the developer; I'm not even going to get started on Spannable.

我看过很多关于使用自定义 TextView 的文章,但他们忘记了它不仅可以实现字体的 textviews 并且还有隐藏在开发人员无法访问的其他视图中的 textviews;我什至不打算开始使用Spanable

You could use an external font utility like:

您可以使用外部字体实用程序,例如:

Calligraphy Font Tool

书法字体工具

BUTThis loops over every view in the application on it's creation and even this utility misses some views (ViewPager renders normal font) then you have the problem that is when Google updates their build tools this will occasionally crash because it needs to target deprecated properties. It's also a little slow as it uses Java's Reflection.

但是,这会在应用程序创建时循环遍历应用程序中的每个视图,甚至该实用程序也错过了一些视图(ViewPager 呈现正常字体),然后您会遇到问题,即当 Google 更新其构建工具时,它偶尔会崩溃,因为它需要针对已弃用的属性。它也有点慢,因为它使用Java 的 Reflection

It's really up to Google to fix this. We need better font support in Android. If you look at the solution from iOS they literally have 100's of fonts built in to select from. Want a custom font? Simply drop a TFF in and it's usable..

这真的取决于谷歌来解决这个问题。我们需要在 Android 中提供更好的字体支持。如果您查看 iOS 的解决方案,它们确实内置了 100 种字体可供选择。想要自定义字体?只需放入一个 TFF 就可以使用了..

For now were now limited to the offering that Google offers us which is extremely limited but fortunately mobile optimized.

现在仅限于 Google 为我们提供的产品,这些产品非常有限,但幸运的是移动优化。