更换皮肤的方式有很多种,有更换背景图片的(图片来源于程序资源文件、sdCard、网络下载)、有更换theme样式的、也有apk的等等。
用apk的方式更换程序皮肤,这样的方式,方便,简单,而且使主程序的apk包较小。
先下载皮肤apk包,安装,然后使现在的程序读取新安装的apk包中的资源文件,下次再打开程序时,照旧读取的是上次设置的apk的资源,如果主题apk被卸载,那末就读取的是默许的资源。
核心代码(完全代码见项目紧缩包)以下:
主程序:
读取已安装了的皮肤包的包名、利用图标和利用名称,固然最重要的实包名,这样可以通过包名,去读取当前皮肤包中的其它资源的资源名称,从而去加载。
private Runnable serachSkin = new Runnable() {
@Override
public void run() {
PackageManager manager = context.getPackageManager();
List<PackageInfo> packages = manager.getInstalledPackages(PackageManager.PERMISSION_GRANTED);
List<PackageInfo> skins = new ArrayList<PackageInfo>();
for (PackageInfo info : packages) { // 遍历已安装的皮肤包
if (info.packageName.startsWith("com.theme.")) { // 与皮肤包的包名对应便可
skins.add(info);
}
}
if (skins.size() > 0) {
Message msg = mHandler.obtainMessage();
msg.obj = skins;
msg.setData(new Bundle());
msg.what = MESSAGE_SEARCHED_SKIN;
mHandler.sendMessage(msg);
} else {
mHandler.sendEmptyMessage(MESSAGE_SEARCHED_SKIN_FOR_NONTHING);
}
}
};
this.setOnThemeChangedListener(new OnThemeChangedListener() {
@Override
public void onChanged(String themePackageName) {
Log.i("", "themePackageName :: " + themePackageName);
try {
Context themeContext = ThemeSecondActivity.this.createPackageContext(themePackageName, Context.CONTEXT_IGNORE_SECURITY);
Resources themeResources = themeContext.getResources();
setControlsStyle(themePackageName, themeResources);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
}
});
/**
* 设置控件新皮肤
* @param themePackageName 皮肤包的包名
* @param themeResources 皮肤包的资源
*/
private void setControlsStyle(String themePackageName, Resources themeResources) {
Log.i("", "themePackageName :: " + themePackageName);
button.setBackground(themeResources.getDrawable(themeResources.getIdentifier("button_selector", "drawable", themePackageName))); // 确保drawable资源文件中有button_selector文件
gridview.setBackgroundColor(themeResources.getColor(themeResources.getIdentifier("background_gridview", "color", themePackageName)));
}
找了很久的apk换肤,类似新浪微博或QQ换肤,找到的案例只是简单的在当前项目中更换主题,或是apk包,但放置到自己的项目中时,抛出空指针或资源文件不存在的异常。
纠其缘由,由于资源文件没有找到,在当前项目中用的是getDrawable(R.drawable.xx)方式来获得图片,这类方式是根据R.drawable.xx对应的1个int值(int值在工程中的gen文件夹下的R.java的class类中)来辨认并加载的,这样要确保主工程与皮肤工程对应的两个值是1样的,如果不1样,便可能出现错位(int值对应到其它的资源),固然还有可能致使空指针或找不到资源文件(int值不存在)。
决解方式是,确保当前读取的res资源是皮肤包的资源,读取方式是:
Context themeContext = ThemeSecondActivity.this.createPackageContext(themePackageName,Context.CONTEXT_IGNORE_SECURITY);
Resources themeResources = themeContext.getResources();
项目紧缩包下载地址:http://download.csdn.net/detail/xue_wei_love/8581235
说明:apk方式更换主题:包括多个页面更换,多个资源更换(可以色彩值、图片、xml文件等自定义资源文件)。 紧缩中中包括4个工程,说明以下: SkinTheme是主工程,SkinRed是红色主题包,SkinGreen是绿色主题包,SkinBlue是蓝色主题包。
参考:
http://www.eoeandroid.com/thread⑴02060⑴⑴.html
http://bbs.csdn.net/topics/390311059
http://www.2cto.com/kf/201204/129474.html
http://blog.csdn.net/vincent_czz/article/details/7276118
http://www.javaapk.com/source/417.html#
http://down.51cto.com/data/622207