Android中通过typeface设置字体

在网上跑图几个小时,终于总结完。
行吧行吧,发车……
开发过程中,布局文件中指定仅限于系统自带的四种字体(android Studio 3.0.1),就如:
这里写图片描述
嫌丑都不喜欢?去下载字体包吧我是免费商用字体下载链接字体下载,下载完成导入到项目,在assets文件夹(和Java文件夹同级,没有新建)中新建fonts文件夹,如图
这里写图片描述

  1. 最简单的替换方式

    Typeface TypeFaceYaHei = Typeface.createFromAsset(mActivity.getAssets(), "fonts/xiaowei.otf");
    ((TextView) findViewById(R.id.tv_practice)).setTypeface(TypeFaceYaHei, Typeface.BOLD);
    
  2. 文件映射的方式进行替换
    在自己的Application中进行字体文件映射,

    private static Typeface TypeFaceYaHei;
    public static void getTypeFace(Activity activity, int i) {

    switch (i) {
        case 1:
            TypeFaceYaHei = Typeface.createFromAsset(mContext.getAssets(), "fonts/xiaowei.otf");
            break;
        case 2:
            TypeFaceYaHei = Typeface.createFromAsset(mContext.getAssets(), "fonts/bufferType.ttf");
            break;
    }
    
    try {
        Field field = Typeface.class.getDeclaredField("MONOSPACE");
        field.setAccessible(true);
        field.set(null, TypeFaceYaHei);
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }}
    

    这样,就能完成每次启动App时完成字体替换的功能!是的,每次启动时。但是这不是我想要的效果!!!?我想要实时更改字体,就行Android手机设置里更改字体一样,选择了想要的字体后,立马完成替换效果。那就继续往下看。

  3. 像Android系统一样实时替换选择的字体的效果


要完成这个效果,我首先想到的方法是这样的:在选择字体之后,
    然后,在每个页面中进行强制刷新页面


     ((ViewGroup) mActivity.findViewById(android.R.id.content)).invalidate();

然后。。。。对不起,没有如预料的进行刷新。

好气啊!!!继续想办法,然后就想到拿到布局对里面的元素进行递归修改属于TextView的控件的字体属性,说干就干

首先拿到字体:

    Typeface.createFromAsset(context.getAssets(), fontPath);

再拿到根布局对象:

    ((ViewGroup) context.findViewById(android.R.id.content)).getChildAt(0);

然后就是递归替换了:

    if (root instanceof TextView) { 
        // 如果是textView,进行替换
        TextView textView = (TextView) root;
        int style = Typeface.NORMAL;
        if (textView.getTypeface() != null) {
            style = textView.getTypeface().getStyle();
        }
        textView.setTypeface(createTypeface(root.getContext(), fontPath), style);
    } else if (root instanceof ViewGroup) {
        // 如果是ViewGroup,再递归这个布局,重复上这个动作
        ViewGroup viewGroup = (ViewGroup) root;
        for (int i = 0; i < viewGroup.getChildCount(); ++i) {
            replaceFont(viewGroup.getChildAt(i), fontPath);
        }
    }

利用方法三,再通过BroadcastRecerver完成全局修改字体的需求。
最后抽象出一个工具类:

/**

* explain
* Created by GerryRun on 2018/4/11 0011.
* e-mail gerryrun@qq.com
*/

public class ReplaceTypefaceUtil {

private static final String TAG = ReplaceTypefaceUtil.class.getSimpleName();


private static Typeface TypeFaceYaHei;

public static void getTypeFace(Activity activity, int i) {

    switch (i) {
        case 1:

            TypeFaceYaHei = Typeface.createFromAsset(activity.getApplication().getAssets(), "fonts/xiaowei.otf");

            ReplaceTypefaceUtil.replaceFont(activity, "fonts/xiaowei.otf");
            break;
        case 2:

            TypeFaceYaHei = Typeface.createFromAsset(activity.getApplication().getAssets(), "fonts/bufferType.ttf");

            ReplaceTypefaceUtil.replaceFont(activity, "fonts/bufferType.ttf");
            break;
    }

    try {
        Field field = Typeface.class.getDeclaredField("MONOSPACE");
        field.setAccessible(true);
        field.set(null, TypeFaceYaHei);
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

public static void replaceFont(@NonNull View root, String fontPath) {
    if (root == null || TextUtils.isEmpty(fontPath)) {
        Log.e(TAG, "root cannot be null");
        return;
    }
    if (root instanceof TextView) {
        // 如果是TextView,进行替换
        TextView textView = (TextView) root;
        int style = Typeface.NORMAL;
        if (textView.getTypeface() != null) {
            style = textView.getTypeface().getStyle();
        }
        textView.setTypeface(createTypeface(root.getContext(), fontPath), style);
    } else if (root instanceof ViewGroup) {
        // 如果是ViewGroup,再递归这个布局,重复上这个动作
        ViewGroup viewGroup = (ViewGroup) root;
        for (int i = 0; i < viewGroup.getChildCount(); ++i) {
            replaceFont(viewGroup.getChildAt(i), fontPath);
        }
    }
}

public static void replaceFont(@NonNull Activity context, String fontPath) {
    replaceFont(getRootView(context), fontPath);
}


public static Typeface createTypeface(Context context, String fontPath) {
    return Typeface.createFromAsset(context.getAssets(), fontPath);
}

/**
 * 获取根布局
 *
 * @param context
 * @return
 */
public static View getRootView(Activity context) {
    return ((ViewGroup) context.findViewById(android.R.id.content)).getChildAt(0);
}

}

用法很简单:

    ((TextView) findViewById(R.id.tv_practice)).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ReplaceTypefaceUtil.getTypeFace(mActivity, 2);
        }
    });

效果图:
这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值