天天看点

[android] TextView 自定义字体 另类统一方案一般设置自定义字体的办法我遇到的实际情况

TextView一次性设置自定义字体-在res/font里的办法

  • 一般设置自定义字体的办法
  • 我遇到的实际情况
    • 工友总是跑的很‘快’
    • 没法使用的第二种方式(将font放在asset下)
    • 本民工最终的解决办法,干净利落!
    • 死磕过程中遇到的难题

一般设置自定义字体的办法

一般有两种方式:

1,将font文件放在res/font/目录下,然后在布局xml中这样写:

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

这样缺点很明显,每个需要的TextView都要在xml里加上这样的属性。工程大了维护起来太恐怖。而且这样也非常不软件工程,于是网上有第二种办法。

2,将font文件放在assets/fonts/目录下,然后自定义MyFontTextView继承TextView,并统一设置字体:

public class MyFontTextView extends android.support.v7.widget.AppCompatTextView {
    public MyFontTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        Typeface typeFace = Typeface.createFromAsset(context.getAssets(), "fonts/my_fonts.ttf");
        setTypeface(typeFace);
    }
           

这种方法一般比较适用,大多数工友能这样做就OK了。但是。。。

我遇到的实际情况

上面两个办法,足够一般项目应用了。

  • 如果是少量地方要自定义字体,用第一种办法。
  • 如果是大范围的TextView要用自定义字体,用第二种办法

但作为android搬砖民工,总是遇得到坑坑的事情。【捂脸】

工友总是跑的很‘快’

我们项目要求UI改变,所有字体几乎都要替换成一个自定义的font。

但工友直接用第一个方式,每个TextView的xml添加一个android:fontFamily属性,简直不要太酸爽。实在是佩服工友任劳任怨,一匹一匹砖慢慢搬的民工精神。

可是!本民工擅长偷懒,绝对不干这种重复劳动!绝对不能面向CV搬砖!

开干!

没法使用的第二种方式(将font放在asset下)

如果要用第二种方式一劳永逸是很简单。但我们font文件大小是10MB数量级。把font文件copy一份放到asset下会让APK包体积有增大对应的size,简直不能忍。

而且因为工友已经大范围Copy + Paste 修改,也不可能改回去。

本民工最终的解决办法,干净利落!

以第二种方式一劳永逸,但保持font文件在res/font目录下的办法,死磕一下午终于研究出来!直接上代码!拿来就能用!

1,在res/values/styles.xml里创建如下style样式:

<style name="font_my_new">
        <item name="android:fontFamily">@font/my_font</item>
    </style>
           

2,NewFontTextView extends TextView,并初始化时如下应用该样式,即可应用对应字体:

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

    private void init(Context context, AttributeSet attrs) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            setTextAppearance(R.style.my_fonts);
        } else {
            setTextAppearance(context, R.style.my_fonts);
        }
           

死磕过程中遇到的难题

1,一开始试想,参考第二种asset/font的方法,把res/font下的字体文件获取到,然后通过setTypeface(typeFace)的方式设置。这里查看了Typeface的对应方法,发现相关的create方法都没法通过res/font目录下的文件创建出Typeface。

其中有两个方法createFromFile(String path)我一开始还报以希望,结果没找到获取res/font对应文件的办法。

2,找到一个这样的办法:

Typeface tf = context.getResources().getFont(R.font.hyqh_40s);
            setTypeface(tf);
           

但很可惜context.getResources().getFont这个方法要求兼容的mini SDK level至少26。现在估计大多数APP的mini SDK 还是16吧。

3,最后研究TextView的源码,根据font_family参数,找到了上面的解决办法。