github上有一个Calligraphy库,这个库可以用来替换字体。核心代码就是CalligraphyLayoutInflater,它继承默认LayoutInflater并且取代默认inflater来渲染整个图层。当你设置好了字体以后自然就会用新字体来渲染文字。但问题是,现在这个库只能实现一开始加载的时候渲染文字,那如果我正在一个Activity里面操作,里面有viewpager,fragment等一大堆组件,然后我切换进设置,在设置里面修改字体再返回这个Activity,此时Activity并没有经历销毁重新生成的过程,所以新字体无法自动应用上去,那怎么办呢?我们可以这么办
(1)配置Calligraphy库
这一步可以解决在新生成的,或者销毁再生成的Activity里面的字体的变化。剩下的就是已经存在的Activity的组件,包括ListView等有缓存机制的
参考:http://www.jianshu.com/p/5d4e6ae8ba4e
(2)遍历修改
对于原生,自定义控件采用遍历修改的方法(还剩下ListView和ViewPager等有缓存机制的组件)
/**
* 遍历修改字体
* @param root 根目录,一般就是最顶层的LinearLayout
*/
private void Traversal(ViewGroup root) {
for (int i = 0; i < root.getChildCount(); i++) {
View view = root.getChildAt(i);
if (view instanceof ViewGroup) {
Traversal((ViewGroup) view);
} else {
String componentName = view.getClass().toString();
Log.e("name", componentName);
checkForChange(view);
}
}
}
private void checkForChange(View view) {
if (view instanceof TextView) {
((TextView) view).setTypeface(mTypeface);
}
if (view instanceof Button) {
((Button) view).setTypeface(mTypeface);
}
if (view instanceof EditText) {
((EditText) view).setTypeface(mTypeface);
}
if (view instanceof AutoCompleteTextView) {
((AutoCompleteTextView) view).setTypeface(mTypeface);
}
if (view instanceof MultiAutoCompleteTextView) {
((MultiAutoCompleteTextView) view).setTypeface(mTypeface);
}
if (view instanceof CheckBox) {
((CheckBox) view).setTypeface(mTypeface);
}
if (view instanceof RadioButton) {
((RadioButton) view).setTypeface(mTypeface);
}
if (view instanceof ToggleButton) {
((ToggleButton) view).setTypeface(mTypeface);
}
if (view instanceof AppCompatTextView) {
((AppCompatTextView) view).setTypeface(mTypeface);
}
if (view instanceof AppCompatButton) {
((AppCompatButton) view).setTypeface(mTypeface);
}
if (view instanceof AppCompatEditText) {
((AppCompatEditText) view).setTypeface(mTypeface);
}
if (view instanceof AppCompatAutoCompleteTextView) {
((AppCompatAutoCompleteTextView) view).setTypeface(mTypeface);
}
if (view instanceof AutoCompleteTextView) {
((AutoCompleteTextView) view).setTypeface(mTypeface);
}
if (view instanceof AppCompatCheckBox) {
((AppCompatCheckBox) view).setTypeface(mTypeface);
}
if (view instanceof AppCompatRadioButton) {
((AppCompatRadioButton) view).setTypeface(mTypeface);
}
if (view instanceof AppCompatCheckedTextView) {
((AppCompatCheckedTextView) view).setTypeface(mTypeface);
}
}
(3)ListView更新字体
在getView函数中调用如下函数,然后在外部调用notifyDataSetChanged刷新
private void updateTypeFace() {
if (mTypeface == null) {
TypeFaceApplication application = (TypeFaceApplication) ((Activity) mContext).getApplication();
path = application.getCurrentAssetsPath();
mTypeface = Typeface.createFromAsset(mContext.getAssets(), path);
} else {
TypeFaceApplication application = (TypeFaceApplication) ((Activity) mContext).getApplication();
String currentPath = application.getCurrentAssetsPath();
if (!currentPath.equals(path)) {
path = currentPath;
mTypeface = Typeface.createFromAsset(mContext.getAssets(), currentPath);
}
}
}
(4)ViewPager
在Fragment的setUserVisibleHint中刷新ListView,一般性的控件已经由之前的遍历Traversal完成
最后贴一下Application的代码
public class TypeFaceApplication extends Application {
private String assetsPath = "fonts/songti.TTF";
@Override
public void onCreate() {
super.onCreate();
CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
.setDefaultFontPath(assetsPath)
.setFontAttrId(R.attr.fontPath)
.build());
}
public void change(String assetsPath) {
this.assetsPath = assetsPath;
CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
.setDefaultFontPath(assetsPath)
.setFontAttrId(R.attr.fontPath)
.build());
}
public String getCurrentAssetsPath() {
return assetsPath;
}
}