换肤框架学习总结

来源:互联网 发布:opengl 游戏编程 编辑:程序博客网 时间:2024/05/24 01:46

学习源

鸣谢:http://www.jianshu.com/p/5eac94143bd6

源码地址

https://github.com/jigongdajiang/FunDemo/tree/master

场景分析

1.黑夜白天模式
2.从服务器下载皮肤资源,加载任意皮肤

核心代码分析

1.根据皮肤文件自己创建资源加载类 Resources AssetManager。核心代码如下:
/** * 根据皮肤资源路径创建对应的Resources */public SkinResource(Context context, String skinPath) {        try{            Resources surperResource = context.getResources();            Configuration configuration = new Configuration();            DisplayMetrics displayMetrics = surperResource.getDisplayMetrics();            AssetManager assetManager = AssetManager.class.newInstance();            //添加本地下载好的皮肤            Method methodAddAssetPath = AssetManager.class.getDeclaredMethod("addAssetPath",String.class);            methodAddAssetPath.setAccessible(true);            methodAddAssetPath.invoke(assetManager,skinPath);            mResources = new Resources(assetManager,displayMetrics,configuration);            //获取皮肤apk的包名            mPackageName = context                    .getPackageManager()                    .getPackageArchiveInfo(skinPath, PackageManager.GET_ACTIVITIES)                    .packageName;        }catch (Exception e){            e.printStackTrace();        }}/** * 根据资源名称 如 @color/main_big_color中的main_big_color 解析资源属性进行重新设置 */@Overridepublic void skin(View view, String resName) {            if(view != null && view instanceof TextView){                SkinResource skinResource = getSkinResource();                ColorStateList color = skinResource.getColorByName(resName);                if(null != color){                    ((TextView)view).setTextColor(color);                }            }}
2.连接View的创建,然后截取其属性信息,用第一步的新资源装在器重置View的皮肤属性信息。核心代码如下:
/** * 通过源码得知,指定自己的LayoutInflaterFactory可以拦截View的创建 */private void installMyViewFactory() {        if (!SkinManager.getInstance().isInit()) {            SkinManager.getInstance().init(this);        }        LayoutInflater layoutInflater = LayoutInflater.from(this);        if (layoutInflater.getFactory() == null) {            //仿照AppCompatActivity 的方法,这里一旦自己设置了,将不会走AppCompatActivity中的工厂            LayoutInflaterCompat.setFactory(layoutInflater, this);        }}/** * 仿照系统的View创建过程,以实现兼容性 */@Overridepublic View onCreateView(View parent, String name, Context context, AttributeSet attrs) {        // 创建View        View view = createView(parent, name, context, attrs);//        Log.e(TAG,"View-->"+view);        // 解析属性 src background textColor        // 1. 一个Activity 对应对个SkinView        List<SkinAttr> skinAttrs = SkinAttrSupport.getSkinAttrs(context, attrs);        if (null != view) {            SkinView skinView = new SkinView(view, skinAttrs);            // 统一交给SkinManager去管理            manageSkinView(skinView);            String currentSkinPath = SkinSpUtil.getInstance().getCurrentSkinPath();            if (SkinConfig.SKIN_FILE_QUALIFIED == SkinManager.getInstance().autoLoadCheckSkinPath(currentSkinPath)) {                //自动切换皮肤                skinView.skin();            }        }        return view;    }

框架的使用

1.所有需要换肤的Activity继承自BaseSkinActivity
2.下载完皮肤直接调用SkinManager.getInstance().loadSkin(skinPath)即可

/** * 点击换肤按钮 */public void skinChange(View view) {        String skinPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "black.skin";        int result = SkinManager.getInstance().loadSkin(skinPath);        if (SkinConfig.SKIN_CHANGE_SUCCESS == result) {            Toast.makeText(this, "换肤成功", Toast.LENGTH_LONG).show();        }}
原创粉丝点击