Android自定义字体

本文介绍了在Android中自定义字体的多种方法,包括通过在assets目录放置字体文件快速设置,提供字体内存缓存以优化性能,以及如何创建自定义TextView类。详细讲述了如何处理textStyle属性,以实现与系统字体样式兼容,并提供了实际操作的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在最近的工作中遇到了设置自定义字体的问题,经过在网上查询相关资料和看源码最终将自定义字体弄明白了,因此写下此博客记录一下,希望能给其他人一些帮助。
对比ios系统,Android中默认的字体在中文显示上是十分难看的,尤其是字号比较大的时候,默认字体样式都会感觉比较粗,所以一般对于产品有追求的设计,都会考虑换一套字体样式。在应用中需要配置不同的字体,而 Android 只能在 xml 中配置系统默认提供的四种字体,需要自定义的字体都需要在 Java 代码中配置

为什么自定义字体

Android系统默认使用的是一款叫Roboto的字体。如果你想要突出一个元素,那么会有很多的选择:颜色,大小,样式(粗体,斜体,普通),另一种方式就是使用不同于系统的字体来装饰你的view。

最快的使用自定义字体的方法

首先我们需要在网上找到自己要设置的字体文件 xxx.ttf 比较好的地方有1001 Free Fonts或者是Google Fonts

然后把下载下来的xxx.ttf文件放到工程的asset/fonts路径下面,如果工程中没有这个路径可以自己建一个这样的路径 建立的方法如图所示
这里写图片描述

建立路径成功之后将xxx.ttf 文件放在该目录下面 如下图所示

这里写图片描述

最后就是将这个字体运用到你想要改变的 TextView 上面。

TextView textView = (TextView)findViewById(R.id.qy_w_subject_tv);
Typeface mCustomFont = Typeface.createFromAsset(getAssets(), "fonts/impact_custom.ttf");
textView.setTypeface(mCustomFont);

这样就结束了,如果想要改变一个Textview的字体就是这么简单,最好的情况就是上面的代码在 onCreate() 方法中进行调用。

在我的工程中就两处用到了自定字体,所以我就用了上面的方法去实现,如果很多地方都需要改变字体可以用下面的方法,下面的方法是从别人的文章中粘贴过来的 仅供参考

提供字体内存缓存

虽然Android现在已经很流畅,但是我们依然应该考虑优化性能。所以,我们应该把自定义的字体缓存起来,这样就不用每次去初始化 方法如下

public class FontCache {

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

    public static Typeface get(String name, Context context) {
        Typeface tf = fontCache.get(name);
        if(tf == null) {
            try {
                tf = Typeface.createFromAsset(context.getAssets(), name);
            }
            catch (Exception e) {
                return null;
            }
            fontCache.put(name, tf);
        }
        return tf;
    }
}

缓存下字体就能让我们不用一直去操作 Assets 文件夹,接下来就能实现一个继承自 TextView 的类。
也就是所谓的自定义View

继承TextView

public class EatFoodyTextView extends TextView {

    public EatFoodyTextView(Context context) {
        super(context);

        applyCustomFont(context);
    }

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

        applyCustomFont(context);
    }

    public EatFoodyTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        applyCustomFont(context);
    }

    private void applyCustomFont(Context context) {
        Typeface customFont = FontCache.getTypeface("SourceSansPro-Regular.ttf", context);
        setTypeface(customFont);
    }
}

开始的三个都是构造函数,里面都调用了 applyCustomFont() 方法,然后从上面的 FontCache 类中拿到缓存的字体文件,这样就不用每个view都去重复的从 Assets中取字体,节约了资源,最后将取到的字体设置到 setTypeface() 中。

使用自定义类

现在我们只需要在XML中直接使用,不需要再写其他的java代码,

<RelativeLayout  
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.futurestudio.foody.views.EatFoodyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/eat_foody_green_dark"
        android:textSize="20sp"
        android:text="Future Studio Blog"
        android:layout_marginBottom="24dp"/>

</RelativeLayout>

我们可以依然使用TextView的其他属性,(textSize,textColor之类的),只需要把 TextView替换成 com.futurestudio.foody.views.EatFoodyTextView,这个前面的是全部的包名,然后就会自己应用字体。
但是使用中会发现,虽然一些TextView的属性比如 textSize 能正常的显示,但是 textStyle 这个属性并不能正常的生效。

复杂一点的操作

添加每个ttf文件
首先将同一个系列的三种样式的 ttf 文件都加到 assets 中
这里写图片描述

在XML中使用textStyle属性
在前面已经讲解了自定义view的使用

<io.futurestud.tutorials.customfont.CustomFontTextView  
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="12dp"
    android:text="http://futurestud.io/blog/"
    android:textSize="18sp"
    android:textStyle="bold"/>

实现CustomFontTextView
为了能继续的使用系统的 android:textStyle 属性,需要一些步骤。
首先需要在代码拿到这个属性的信息,这只需要一行代码:

int textStyle = attrs.getAttributeIntValue(ANDROID_SCHEMA, "textStyle", Typeface.NORMAL);

attr 这个值是来自 TextView 第二个构造函数中参数,我们可以使用这个对象的 getAttributeIntValue() 方法获取XML的属性。

先看一下上面代码中的 ANDROID_SCHEMA 这个参数,这个是一个常量,定义在XML的最顶部中(xmlns:android=”http://schemas.android.com/apk/res/android” ),第二个参数就是定义的属性名,最后一个参数是默认值,如果这个属性没有设置,那么就会选择 Typeface.NORMAL。
当我们考虑了样式之后,完善一下代码,全部的代码看起来就像下面这样

public class CustomFontTextView extends TextView {

    public static final String ANDROID_SCHEMA = "http://schemas.android.com/apk/res/android";

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

        applyCustomFont(context, attrs);
    }

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

        applyCustomFont(context, attrs);
    }

    private void applyCustomFont(Context context, AttributeSet attrs) {
        int textStyle = attrs.getAttributeIntValue(ANDROID_SCHEMA, "textStyle", Typeface.NORMAL);

        Typeface customFont = selectTypeface(context, textStyle);
        setTypeface(customFont);
    }

    private Typeface selectTypeface(Context context, int textStyle) {
        /*
        * information about the TextView textStyle:
        * http://developer.android.com/reference/android/R.styleable.html#TextView_textStyle
        */
        switch (textStyle) {
            case Typeface.BOLD: // bold
                return FontCache.getTypeface("SourceSansPro-Bold.ttf", context);

            case Typeface.ITALIC: // italic
                return FontCache.getTypeface("SourceSansPro-Italic.ttf", context);

            case Typeface.BOLD_ITALIC: // bold italic
                return FontCache.getTypeface("SourceSansPro-BoldItalic.ttf", context);

            case Typeface.NORMAL: // regular
            default:
                return FontCache.getTypeface("SourceSansPro-Regular.ttf", context);
        }
}

这样我们的自定义字体就能使用标准的应用字体样式 textStyle。

看看成果
首先我们在XML中写一些布局,包括原生的 Roboto 字体以及不同形式的自定义字体。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="12dp"
        android:text="http://futurestud.io/blog/"
        android:textSize="18sp"/>

    <io.futurestud.tutorials.customfont.CustomFontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="12dp"
        android:text="http://futurestud.io/blog/"
        android:textSize="18sp"/>

    <io.futurestud.tutorials.customfont.CustomFontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="12dp"
        android:text="http://futurestud.io/blog/"
        android:textSize="18sp"
        android:textStyle="bold"/>

    <io.futurestud.tutorials.customfont.CustomFontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="12dp"
        android:text="http://futurestud.io/blog/"
        android:textSize="18sp"
        android:textStyle="italic"/>

</LinearLayout>

这里写图片描述

setTypeface(Typeface tf)源码
这里写图片描述

参考文章:
http://www.jianshu.com/p/38f475fc07ad
http://www.jianshu.com/p/6778d048d8c6
https://developer.android.com/reference/android/graphics/Typeface.html#createFromAsset(android.content.res.AssetManager, java.lang.String)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值