简介
前面两个项目
- android架构师之路——修改app字体讲解了LayoutInflaterCompat.setFactory2的使用方式
- android架构师之路——以修改一个图片文件方式讲解APP换肤原理讲解了换肤的原理
现在我们就在具体实践中,讲解一下更多的使用场景
项目结构
- app:主项目目录
- app_skin:资源项目,生成的apk放在sdcard目录
- lib_skin:lib包,主要的换肤代码就在这里
实现方式
主入口MyApplication
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
SkinManager.init(this);
}
}
SkinManager是实现换肤的管理类方法
- skinManager构造方法
private SkinManager(Application application) {
mContext = application;
//共享首选项 用于记录当前使用的皮肤
SkinPreference.init(application);
//资源管理类 用于从 app/皮肤 中加载资源
SkinResources.init(application);
//注册Activity生命周期
skinActivityLifecycle = new SkinActivityLifecycle();
application.registerActivityLifecycleCallbacks(skinActivityLifecycle);
//加载皮肤
loadSkin(SkinPreference.getInstance().getSkin());
}
- 加载制定路径的资源文件
/**
* 记载皮肤并应用
*
* @param skinPath 皮肤路径 如果为空则使用默认皮肤
*/
public void loadSkin(String skinPath) {
if (TextUtils.isEmpty(skinPath)) {
//记录使用默认皮肤
SkinPreference.getInstance().setSkin("");
//清空资源管理器 皮肤资源属性
SkinResources.getInstance().reset();
} else {
try {
//反射创建AssetManager 与 Resource
AssetManager assetManager = AssetManager.class.newInstance();
//资源路径设置 目录或压缩包
Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
addAssetPath.invoke(assetManager, skinPath);
Resources appResource = mContext.getResources();
//根据当前的显示与配置(横竖屏、语言等)创建Resources
Resources skinResource = new Resources(assetManager, appResource.getDisplayMetrics(), appResource.getConfiguration());
//记录
SkinPreference.getInstance().setSkin(skinPath);
//获取外部Apk(皮肤包) 包名
PackageManager mPm = mContext.getPackageManager();
PackageInfo info = mPm.getPackageArchiveInfo(skinPath, PackageManager.GET_ACTIVITIES);
String packageName = info.packageName;
SkinResources.getInstance().applySkin(skinResource, packageName);
} catch (Exception e) {
e.printStackTrace();
}
}
//通知采集的View 更新皮肤
//被观察者改变 通知所有观察者
setChanged();
notifyObservers(null);
}
SkinPreference主要用来记录资源文件地址
public class SkinPreference {
private static final String SKIN_SHARED = "skins";
private static final String KEY_SKIN_PATH = "skin-path";
private static SkinPreference instance;
private final SharedPreferences mPref;
public static void init(Context context) {
if (instance == null) {
synchronized (SkinPreference.class) {
if (instance == null) {
instance = new SkinPreference(context.getApplicationContext());
}
}
}
}
public static SkinPreference getInstance() {
return instance;
}
private SkinPreference(Context context) {
mPref = context.getSharedPreferences(SKIN_SHARED, Context.MODE_PRIVATE);
}
public void setSkin(String skinPath) {
mPref.edit().putString(KEY_SKIN_PATH, skinPath).apply();
}
public String getSkin() {
return mPref.getString(KEY_SKIN_PATH, null);
}
}
SkinResources皮肤资源加载类
-
获得资源包的R文件中的id
/**
* 获得资源的R文件中的id
* @param resId
* &#