Android实现apk插件方式换肤

  • 2019 年 10 月 14 日
  • 笔记

换肤思路:

1.什么时候换肤?

xml加载前换肤,如果xml加载后换肤,用户将会看见换肤之前的色彩,用户体验不好。

2.皮肤是什么?

皮肤就是apk,是一个资源包,包含了颜色、图片等。

3.什么样的控件应该进行换肤?

包含背景图片的控件,例如textView文字颜色。

4.皮肤与已安装的资源如何匹配?

资源名字匹配

 

 

步骤:

1.xml加载前换肤,意味着需要将所需要换肤的控件收集起来。因此要监听xml加载的过程。

 1 public class BaseActivity extends Activity {   2   3     SkinFactory skinFactory;   4   5     @Override   6     protected void onCreate(@Nullable Bundle savedInstanceState){   7         super.onCreate(savedInstanceState);   8   9         //监听xml生成的过程  10         skinFactory = new SkinFactory();  11         LayoutInflaterCompat.setFactory(getLayoutInflater(),skinFactory);  12     }  13 }

 

2.需要换肤的控件收集到一个容器中并且不更改自己的逻辑直接换肤(例如:不用在每个需要换肤的空间里面加上: “ app:…… ”  自定义控件属性)

思考:

(1)安装的apk的id与皮肤id是否一样?

(2)图片的资源、颜色资源都对应R自动生成的id

(3)皮肤包的资源id、R文件的资源id以及app里R文件的资源的id是否是一样的?——是不一样的

 

3.一个activity有多个控件(SkinView) 一个控件对应多个换肤属性(SkinItem)

SkinItem来封装这些值:

  • attrName-属性名(background)
  • attrValue-属性值id 十六进制(@color/colorPrimaryDark)
  • attrType–类型(color)
  • Id(R文件的id)
 1 class SkinItem{   2         // attrName   background   3         String attrName;   4   5         int refId;   6         // 资源名字  @color/colorPrimaryDark   7         String attrValue;   8         //  drawable color   9         String attrType;  10  11         public SkinItem(String attrName, int refId, String attrValue, String attrType) {  12             this.attrName = attrName;  13             this.refId = refId;  14             this.attrValue = attrValue;  15             this.attrType = attrType;  16         }  17  18         public String getAttrName() {  19             return attrName;  20         }  21  22         public int getRefId() {  23             return refId;  24         }  25  26         public String getAttrValue() {  27             return attrValue;  28         }  29  30         public String getAttrType() {  31             return attrType;  32         }  33     }

SkinView:

1 class SkinView{  2         private View view;  3         private List<SkinItem> list;  //收集需要换肤的集合  4  5         public SkinView(View view, List<SkinItem> list) {  6             this.view = view;  7             this.list = list;  8         }  9     }

 

4.收集完毕后,应用换肤 (xml加载过程中换肤)

 

 

创建SkinManager去获得皮肤apk,app通过SkinManager获取皮肤apk

(1)加载皮肤包(loadSkin):通过反射获得AsserManager的addAssetpath()方法,再通过这个方法获得皮肤apk,从而实例化skinResource;再通过PackageManager.getPackageArchiveInfo(path,PackageManager.GET_ACTIVITIES).packageName;获得皮肤包名

(2)获取颜色(getColor):判断skinResource是否为空;拿到res的名字,eg:通过“colorAccent”去寻找id