因为ceo提到换肤功能,猜想后期项目可能会用,所以紧急学习,发现皮肤集成的themeskinning,于是学习之。不过这个项目有个缺点,就是字体不能网络下载,作者可能忘了写,于是自己补充,因为没有服务器支持,补充部分没有测试过,所以可能补充的部分有问题,如果使用发现问题的,请马上提出来。

补充部分:

(1)补充SkinManager两个方法:

package solid.ren.skinlibrary.loader;


/**
* load skin form local
* <p>
* eg:theme.skin
* </p>
*
* @param fontName the name of font(in assets/font)
* @param callback load Callback
*/
public void loadFont(final String fontName, final SkinLoaderListener callback) {

new AsyncTask<String, Void, Resources>() {

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
* <p>
* eg:https://raw.githubusercontent.com/burgessjp/ThemeSkinning/master/app/src/main/assets/skin/theme.skin
* </p>
*
* @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


提供的文件内有原项目改装版,就是添加了上述字体的部分,对原功能没影响