因为ceo提到换肤功能,猜想后期项目可能会用,所以紧急学习,发现皮肤集成的themeskinning,于是学习之。不过这个项目有个缺点,就是字体不能网络下载,作者可能忘了写,于是自己补充,因为没有服务器支持,补充部分没有测试过,所以可能补充的部分有问题,如果使用发现问题的,请马上提出来。
补充部分:
(1)补充SkinManager两个方法:
package solid.ren.skinlibrary.loader;
/**
* load skin form local
*
* eg:theme.skin
*
*
* @param fontName the name of font(in assets/font)
* @param callback load Callback
*/
public void loadFont(final String fontName, final SkinLoaderListener callback) {
new AsyncTask() {
protected void onPreExecute() {
if (callback != null) {
callback.onStart();
}
}
@Override
protected Resources doInBackground(String... params) {
try {
if (params.length == 1) {
String fontPkgPath = SkinFileUtils.getFontDir(context) + File.separator + params[0];
SkinL.i(TAG, "fontPackagePath:" + fontPkgPath);
File file = new File(fontPkgPath);
if (!file.exists()) {
return null;
}
PackageManager mPm = context.getPackageManager();
PackageInfo mInfo = mPm.getPackageArchiveInfo(fontPkgPath, PackageManager.GET_ACTIVITIES);
skinPackageName = mInfo.packageName;
AssetManager assetManager = AssetManager.class.newInstance();
Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
addAssetPath.invoke(assetManager, fontPkgPath);
Resources superRes = context.getResources();
Resources skinResource = ResourcesCompat.getResources(assetManager, superRes.getDisplayMetrics(), superRes.getConfiguration());
SkinConfig.saveFontPath(context, params[0]);
fontPath = fontPkgPath;
return skinResource;
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
protected void onPostExecute(Resources result) {
mResources = result;
if (mResources != null) {
loadFont(fontName);
if (callback != null) callback.onSuccess();
} else {
if (callback != null) callback.onFailed("没有获取到资源");
}
}
}.execute(fontName);
}
/**
* load skin form internet
*
* eg:https://raw.githubusercontent.com/burgessjp/ThemeSkinning/master/app/src/main/assets/skin/theme.skin
*
*
* @param fontUrl the url of font
* @param callback load Callback
*/
public void loadFontFromUrl(String fontUrl, final SkinLoaderListener callback) {
String fontPath = SkinFileUtils.getFontDir(context);
final String fontName = fontUrl.substring(fontUrl.lastIndexOf("/") + 1);
String fontFullName = fontPath + File.separator + fontPath;
File fontFile = new File(fontFullName);
if (fontFile.exists()) {
loadFont(fontName,callback);
return;
}
Uri downloadUri = Uri.parse(fontUrl);
Uri destinationUri = Uri.parse(fontFullName);
DownloadRequest downloadRequest = new DownloadRequest(downloadUri)
.setRetryPolicy(new DefaultRetryPolicy())
.setDestinationURI(destinationUri)
.setPriority(DownloadRequest.Priority.HIGH);
callback.onStart();
downloadRequest.setStatusListener(new DownloadStatusListenerV1() {
@Override
public void onDownloadComplete(DownloadRequest downloadRequest) {
loadFont(fontName,callback);
}
@Override
public void onDownloadFailed(DownloadRequest downloadRequest, int errorCode, String errorMessage) {
callback.onFailed(errorMessage);
}
@Override
public void onProgress(DownloadRequest downloadRequest, long totalBytes, long downloadedBytes, int progress) {
callback.onProgress(progress);
}
});
ThinDownloadManager manager = new ThinDownloadManager();
manager.add(downloadRequest);
}
(2)SkinFileUtils补充:
package solid.ren.skinlibrary.utils;
/**
* 得到存放皮肤的目录
*
* @param context the context
* @return 存放皮肤的目录
*/
public static String getFontDir(Context context) {
File fontDir = new File(getCacheDir(context), SkinConfig.FONT_DIR_NAME);
if (!fontDir.exists()) {
fontDir.mkdirs();
}
return fontDir.getAbsolutePath();
}
集成步骤:
1.gradle添加
compile 'com.solid.skin:skinlibrary:2.0.0-beta3'
或使用本地
skinlibrary
源码地址:https://github.com/burgessjp/ThemeSkinning
如果要进行上述改装,需要下载源码,更改skinlibrary,本文提供的资源内也有。 本文提供的资源里面也有。
2.自定义application继承SkinBaseApplication
需要使用皮肤的activity继承SkinBaseActivity
需要使用皮肤的fragment继承SkinBaseFragment
3.非font和background属性,需要在application中配置
SkinConfig.addSupportAttr("radioButtonAttr", new RadioButtonAttr());
如果非常用控件,还需配置:
dynamicAddView(textView1, "textColor", R.color.item_tv_title_color);
状态栏配置:
SkinConfig.setCanChangeStatusColor(true);
建议还是拿出库来改装,否则在自定义布局中无法使用,反正基本都是实现IDynamicNewView
public class RadioButtonAttr extends SkinAttr {
@Override
protected void applySkin(View view) {
if (view instanceof RadioButton) {
if (isDrawable()) {
RadioButton radioButton = (RadioButton) view;
Drawable drawable = SkinResourcesUtils.getDrawable(attrValueRefId);
radioButton.setButtonDrawable(drawable);
}
}
}
}
说白就是配什么属性要说明,像上面例子就是设置radiobutton样式
4进行某操作后触发替换:
SkinManager.getInstance().loadSkin(...);
或
SkinManager.getInstance().loadSkinFromUrl(...);
字体:
SkinManager.getInstance().loadFont(fontName);
5.讲下怎么生成皮肤包:
(1)拷贝我提供的资源中的skinpackage或者新建个工程,把app模块的main目录删掉,然后把原项目module中的res目录拷贝到该module中
(2)删除res/layout,删除不需要替换的部分,删除每个activity对应的主题(总之和控件无关的都删掉)
(3)Package->Genarate Signed APK选择或添加新的keystore生成皮肤,将后缀改为.skin,注意选择生成时module别选错了
(4)若需要本地,拷贝到asset目录,没有就右键main->new->image asset创建,然后内部建立font和skin两个文件夹
(5)如果是网络下载,将.skin包发给服务器,服务器提供接口获取皮肤图片和url
(6)如果是本地,字体放入asset/font,皮肤放入skin/font
提供的文件内有原项目改装版,就是添加了上述字体的部分,对原功能没影响