Android 动态换肤框架,支持动态加载插件资源,无需重启Activity,拓展能力很强
Pixel 4 XL Android 13 实机测试
95b973c2ead665e65a1e17461d55e276.mp4
将需要换肤页面的Activity继承自SkinBaseActivity
public class MainActivity extends SkinBaseActivity {
//....
}
SkinManager.INSTANCE.loadSkinFile(Environment.getExternalStorageDirectory() + "/skin.apk");
对于Assets目录,使用
SkinManager.INSTANCE.loadSkinAssets("skin.apk");
加载Assts文件,会copy一份到sdcard下,具体路径为:
/sdcard/Android/data/${packageName}/cache/skinCache/**.apk
更推荐使用SkinManager.INSTANCE.loadSkinFile
使用app:skinEnable="true or false"
来决定View是否开启换肤。
优先级大于setSkinGlobalEnable
,默认全局开启
框架默认支持background
、src
、textColor
、text
常用资源切换,若需要增加功能
使用addSkinAttrHolder
方法添加需要的属性
public <T> void addSkinAttrHolder(String attrName, ISkinMethodHolder<? extends View, ?> methodHolder)
这个方法接收两个参数
- 第一个参数是属性名,如:
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColorHint="@color/color_blue_50" />
这里有一个EditText
,我们要增加textColorHint的换肤能力,那么属性名就是textColorHint
.
- 第二个参数是属性
set
方法的方法引用
,如EditText::setHintTextColor
示例
ISkinMethodHolder<EditText, Integer> setHintTextColor = EditText::setHintTextColor;
SkinManager.INSTANCE.addSkinAttrHolder("textColorHint", setHintTextColor);
到这里,我们增加一个换肤能力就实现了!!!
请注意,ISkinMethodHolder<EditText, Integer>
接口中的第二个类型表示的是set
方法的参数类型
必须是设置资源值的方法,不能使用设置资源Id的重载方法!!!
原因是我们即使我们传入资源包中的资源ID,set
方法内部也是通过APP的Resource对象获取的值
关于复杂参数的set
方法处理
比如TextView
的setTextSize()
方法,接受两个参数:
我们还是可以通过方法引用来实现,这里需要转化一下
处理方式:
static void setTextSize(TextView view, float px) {
view.setTextSize(TypedValue.COMPLEX_UNIT_PX, px);
}
public static final ISkinMethodHolder<TextView, Float> setTextSize = SkinMethod::setTextSize;
// ......
SkinManager.INSTANCE.addSkinAttrHolder("textSize", setTextSize);
关于自定义View,请提供属性的set
方法即可
使用ISkinMethodHolder.andThen()
来转换成MethodAcceptAndThen
对象
这是对ISkinMethodHolder
的功能拓展,增加了一个after
操作,用于这条属性在执行完换肤之后的操作.
注意!! 只有设置了 app:skinMethodTag=""
属性的View
才会执行此操作,未设置完全不会执行
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="默认主题"
app:skinMethodTag="title"
android:textColor="@color/color_blue_50" />
示例
//文字颜色
ISkinMethodHolder<TextView, Integer> setTextColor = TextView::setTextColor;
MethodAcceptAndThen<TextView, Integer> setTextColorAndThen = setTextColor.andThen((textView, integer) -> {
if ("title".equals(textView.getTag(R.id.skinMethodTagID))) {
textView.setText("春节主题皮肤");
}
});
SkinManager.INSTANCE.addSkinAttrHolder("setTextColor", setTextColorAndThen);
使用ISkinMethodHolder.proxy()
来转换成MethodAcceptProxy
对象
这是对ISkinMethodHolder
的功能拓展,代理当前set
方法,实现自己逻辑.
示例
ISkinMethodHolder<View, Drawable> setBackground = View::setBackground;
MethodAcceptProxy<View, Drawable> setBackgroundProxy = setBackground.proxy((view, value, methodHolder) -> {
if ("mProxyTag".equals(textView.getTag(R.id.skinMethodTagID))) {
//You can do something
}
});
SkinManager.INSTANCE.addSkinAttrHolder("setBackground", setBackgroundProxy);
注意!! 只有设置了app:skinMethodTag=""
属性的View
才会执行此操作,未设置完全不会执行
loadDefault() | 重置换肤,切换为默认 |
---|---|
getSkinResource() | 获取资源包的资源对象,如果为空,返回APP的资源对象 |
isSkinState() | 是否为换肤状态 |
isSkinGlobalEnable() | 是否已启用全局换肤 |
setSkinGlobalEnable(boolean enable) | 设置是否启用全局换肤开关,默认为true,可通过{app:skinEnable="boolean"}属性单独给View设置 |
getColor() | 根据资源ID获取资源包中的Color颜色值 |
getDrawable() | 根据资源ID获取资源包中的drawable对象 |
getString() | 根据资源ID获取资源包中的字符 |
getDimension() | 根据资源ID获取资源包中的Dimension资源值 |
getSkinResId(@IdRes int resId) | 根据资源Id获取到皮肤包中的Id. |