27
2017
09

android全局替换字体最新方案

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;
    }
}
上一篇:Android https-json解析 下一篇:adb shell 命令操作应用数据文件