项目需要进行主题更换,防Go桌面那样以apk形式进行主题更换,到网上找了下资料,资料不多,所以把自己学习的东西整理一下,以便以后查阅,同时也希望能帮到有需要的人:
一、网上找到的
网址:http://edison-cool911.iteye.com/blog/991048
这个方法要求主题apk中的资源id和应用资源id完全相同,如果应用资源多的话,会出现主题包偏大的情况。
二、我的方法
首先跟上面的一样,用context = createPackageContext(packageName,
CONTEXT_IGNORE_SECURITY);创建一个主题apk的context,再用context得到resources,用Resources类的getIdentifier(name, defType, defPackage)方法,该方法是得到对应名称的资源的id如果资源不存在则返回0:
Name:对应的资源名称(如资源R.drawable.ic_launcher--->name为“ic_launcher”)
defType:对应资源的类型(如资源R.drawable.ic_launcher--->defType为“drawable”)
defPackage:主题apk的包名
有了这个方法就可以用下面的代码取得主题包中的资源:
if (resId == 0) { // 图片不存在,使用默认图片 Resources res = skinContext.getResources(); int id = res.getIdentifier(drawableName, "drawable", skinInfo.context.getPackageName()); drawable = res.getDrawable(id); } else { // 图片存在 Resources res = skinInfo.skinContext.getResources(); drawable = res.getDrawable(R.drawable.xxx); }
还有一个会用到的selector,所以要用程序实现selector,这就要用到StateListDrawable这个类
通过上面的方法得到selector中对应的资源,再通过下面的方法得到selector:
public static StateListDrawable newSelector(Drawable pressed, Drawable focused, Drawable normal) { StateListDrawable states = new StateListDrawable(); states.addState(new int[] { android.R.attr.state_pressed }, pressed); states.addState(new int[] { android.R.attr.state_focused }, focused); states.addState(new int[] { -android.R.attr.state_pressed }, normal); return states; }
用view的setBackgroundDrawable()把上面方法的返回设置进去就可以了。。。
三、关于列出已安装的主题
我的方法:主题包取一个特定前缀的包名,通过遍历安装包得到特定前缀的包,再检查一下包的签名(关于签名检查,我的代码收藏里面有,百度一下也好多)