在网上跑图几个小时,终于总结完。
行吧行吧,发车……
开发过程中,布局文件中指定仅限于系统自带的四种字体(android Studio 3.0.1),就如:
嫌丑都不喜欢?去下载字体包吧我是免费商用字体下载链接字体下载,下载完成导入到项目,在assets文件夹(和Java文件夹同级,没有新建)中新建fonts文件夹,如图
最简单的替换方式
Typeface TypeFaceYaHei = Typeface.createFromAsset(mActivity.getAssets(), "fonts/xiaowei.otf"); ((TextView) findViewById(R.id.tv_practice)).setTypeface(TypeFaceYaHei, Typeface.BOLD);
文件映射的方式进行替换
在自己的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手机设置里更改字体一样,选择了想要的字体后,立马完成替换效果。那就继续往下看。
像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);
}
});
效果图: