268

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

这是我的代码:

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

谁能让我摆脱这个问题?

4

21 回答 21

231

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

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

资产/字体

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

于 2010-09-06T11:45:20.940 回答
56

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

  1. 您不必引入自己的重写 TextView 组件,您可以使用内置的 TextView
  2. 您可以使用 gradle 轻松包含该库
  3. 该库不限制您对字体的选择;您只需将您喜欢的添加到资产目录
  4. 您不仅可以获得自定义文本视图——所有其他基于文本的 Android 组件也将使用您的自定义字体显示。
于 2014-05-26T14:48:03.520 回答
33

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

这是自定义文本视图:

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

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

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

这就是你如何使用它。我将使用相对布局来包装它并显示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>
于 2014-09-28T20:29:43.483 回答
14

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

于 2010-09-06T11:35:25.150 回答
14

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

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

伴随着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>

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

于 2014-03-03T12:59:11.043 回答
13

最好的方法从 Android O 预览版是这样的:

它只有在你有 android studio-2.4 或更高版本时才有效

  1. 右键单击res 文件夹并转到New > Android resource directory。将出现新建
    资源目录窗口。
  2. 在资源类型列表中,选择字体,然后单击确定。
  3. 在字体文件夹中添加您的字体文件。下面的文件夹结构生成R.font.dancing_scriptR.font.la_laR.font.ba_ba
  4. 双击字体文件以在编辑器中预览文件的字体。

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

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

将字体添加到 TextView:

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

从文档

使用字体

所有步骤都是正确的。

于 2017-04-04T00:27:47.527 回答
12

对于 android 中的自定义字体,在 assets 文件夹中创建一个文件夹,将其命名为“fonts”,将所需的 fonts.ttf 或 .otf 文件放入其中。

如果你扩展 UIBaseFragment:

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

否则如果扩展活动:

Typeface font = Typeface.createFromAsset(getContext().getAssets(), "fonts/Arial.ttf");
        tv.setTypeface(font);
于 2014-09-03T14:22:10.700 回答
7

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

导入他们的 .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" />
于 2013-08-07T06:47:03.487 回答
4

由于我对 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"/>

或这个:

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

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

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

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

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

你问的魔法课是什么?主要是从另一个 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;
    }
}
于 2016-08-12T03:10:16.633 回答
4

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

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

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

书法字体工具

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

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

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

于 2016-12-09T08:33:19.287 回答
2

确保在调用 super 和调用 setContentView( )之后将上述代码粘贴到 onCreate( ) 中。这个小细节让我挂了一段时间。

于 2013-05-15T21:34:47.560 回答
2

您可以使用简单易用的EasyFonts第三方库为您的TextView. 通过使用这个库,您不必担心下载字体并将其添加到 assets/fonts 文件夹中。还有关于字体对象的创建。

代替

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

简单地:

TextView myTextView = (TextView)findViewById(R.id.myTextView);
myTextView.setTypeface(EasyFonts.robotoThin(this));

该库还提供以下字体。

  • 机器人
  • 机器人衬线
  • 机器人机器人
  • 自由
  • 有趣的提高者
  • 安卓国度
  • 绿色鳄梨
  • 认出
于 2015-06-25T18:06:11.437 回答
2

Android 8.0中,在应用程序中使用自定义字体变得很容易downloadable fonts。我们可以直接将字体添加到res/font/ folder项目文件夹中,这样字体就会自动在 Android Studio 中可用。

文件夹下 res 名称字体和类型设置为字体

现在将fontFamily属性设置为字体列表或单击更多并选择您选择的字体。这将为您的 TextView添加tools:fontFamily="@font/your_font_file"行。

这将自动生成几个文件。

1.在 values 文件夹中,它将创建fonts_certs.xml.

2.在 Manifest 中,它将添加以下行:

  <meta-data
            android:name="preloaded_fonts"
            android:resource="@array/preloaded_fonts" /> 

3. preloaded_fonts.xml

<resources>
    <array name="preloaded_fonts" translatable="false">
        <item>@font/open_sans_regular</item>
        <item>@font/open_sans_semibold</item>
    </array>
</resources>
于 2017-12-07T11:02:38.933 回答
1

我有同样的问题,TTF没有出现。我更改了字体文件,并且使用相同的代码它正在工作。

于 2013-05-18T19:54:37.603 回答
1

如果要从网络加载字体或轻松设置字体样式,可以使用:

https://github.com/shellum/fontView

例子:

<!--Layout-->
<com.finalhack.fontview.FontView
        android:id="@+id/someFontIcon"
        android:layout_width="80dp"
        android:layout_height="80dp" />

//Java:
fontView.setupFont("http://blah.com/myfont.ttf", true, character, FontView.ImageType.CIRCLE);
fontView.addForegroundColor(Color.RED);
fontView.addBackgroundColor(Color.WHITE);
于 2013-05-29T21:13:37.297 回答
1

好吧,七年后,您可以使用库 26++textView轻松更改整个应用程序或您想要的内容。android.support

例如:

创建你的字体包app/src/res/font并将你的字体移动到其中。

在此处输入图像描述

在您的应用主题中,只需将其添加为 fontFamily:

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

仅与以下一起使用的示例textView

<style name="fontTextView" parent="@android:style/Widget.TextView">
    <item name="android:fontFamily">monospace</item>
</style>

并添加到您的主题中:

<item name="android:textViewStyle">@style/fontTextView</item>

目前它适用于8.1 到 4.1 API Jelly Bean,而且范围很广。

于 2017-11-01T17:36:59.670 回答
1

更新答案: Android 8.0(API 级别 26)引入了一项新功能,即 XML 字体。只需在运行 Android 4.1(API 级别 16)及更高版本的设备上使用 XML 中的字体功能,使用支持库 26。

看到这个链接


旧答案

有两种自定义字体的方法:

!!!我在 assets/fonts/iran_sans.ttf 中的自定义字体



方式1: Refrection Typeface.class ||| 最好的办法

在类extends Application中调用FontsOverride.setDefaultFont(),这段代码会导致所有软件字体发生变化,甚至Toasts字体

应用控制器.java

public class AppController extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        //Initial Font
        FontsOverride.setDefaultFont(getApplicationContext(), "MONOSPACE", "fonts/iran_sans.ttf");

    }
}

FontsOverride.java

public class FontsOverride {

    public static void setDefaultFont(Context context, String staticTypefaceFieldName, String fontAssetName) {
        final Typeface regular = Typeface.createFromAsset(context.getAssets(), fontAssetName);
        replaceFont(staticTypefaceFieldName, regular);
    }

    private 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();
        }
    }
}



方式2:使用setTypeface

对于特殊视图,只需调用 setTypeface() 即可更改字体。

CTextView.java

public class CTextView extends TextView {

    public CTextView(Context context) {
        super(context);
        init(context,null);
    }

    public CTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context,attrs);
    }

    public CTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context,attrs);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public CTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context,attrs);
    }

    public void init(Context context, @Nullable AttributeSet attrs) {

        if (isInEditMode())
            return;

        // use setTypeface for change font this view
        setTypeface(FontUtils.getTypeface("fonts/iran_sans.ttf"));

    }
}

FontUtils.java

public class FontUtils {

    private static Hashtable<String, Typeface> fontCache = new Hashtable<>();

    public static Typeface getTypeface(String fontName) {
        Typeface tf = fontCache.get(fontName);
        if (tf == null) {
            try {
                tf = Typeface.createFromAsset(AppController.getInstance().getApplicationContext().getAssets(), fontName);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
            fontCache.put(fontName, tf);
        }
        return tf;
    }

}
于 2017-11-04T05:38:48.133 回答
0

从 API 26 开始的正确方法在此处的官方文档中进行了描述:

https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html

这涉及将 ttf 文件放在 res/font 文件夹中并创建一个字体系列文件。

于 2017-09-28T19:18:04.947 回答
0

是的,正如Dipali所说,可下载字体非常容易。

这就是你的做法...

  1. 放置一个TextView.
  2. 在属性窗格中,选择fontFamily下拉列表。如果它不存在,请在下方找到插入符号(> 并单击它以展开textAppearance)。
  3. 展开font-family下拉菜单。
  4. 在小列表中,一直向下滚动直到看到more fonts
  5. 这将打开一个对话框,您可以从中搜索Google Fonts
  6. 使用顶部的搜索栏搜索您喜欢的字体
  7. 选择你的字体。
  8. 选择您喜欢的字体样式(即粗体、普通、斜体等)
  9. 在右窗格中,选择单选按钮Add font to project
  10. 点击确定。现在你的 TextView 有你喜欢的字体了!

奖励:如果您想使用所选字体在应用程序中使用文本设置所有样式,只需添加<item name="android:fontfamily">@font/fontnamehere</item>到您的styles.xml

于 2017-12-13T12:37:23.183 回答
0

现在支持的最简单的android解决方案!

在 xml 中使用自定义字体:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:fontFamily="@font/[your font resource]"/>

看详情:

https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html

于 2018-01-05T02:51:46.820 回答
0
  • 打开您的项目并选择左上角的项目
  • 应用程序--> src -->主程序
  • 右键单击主并创建目录并将其命名为资产
  • 右键单击以评估并创建新目录并将其命名为字体
  • 你需要找到免费字体,比如免费字体
  • 把它交给你的 Textview 并在你的 Activity 类中调用它
  • 将字体复制到字体文件夹中
  • TextView txt = (TextView) findViewById(R.id.txt_act_spalsh_welcome); Typeface font = Typeface.createFromAsset(getAssets(), "fonts/Aramis Italic.ttf"); txt.setTypeface(font);

字体名称必须正确且玩得开心

于 2018-01-29T12:42:00.247 回答