支持应用内和插件式的应用换肤框架

最后编辑于2018年9月18日

效果图:

引入
下载SkinChangeDemo,你的项目可以依赖其中的skinchange模块

dependencies {
     compile project(':skinchange')
}

或者添加远程依赖

dependencies {
    compile 'cn.msz.skinchange:skinchange:0.0.3'
}

 使用:
step1、制作你需要的SkinAttr(一个给特定view特定属性赋值的一个类):
           1、继承SkinAttr,重写setViewAttr方法;
           2、判断所赋的值是哪种类型;
           3、调用该类型view给该属性赋值的方法。
如:

public class BackgroundAttr extends SkinAttr {
    @Override
    public void setViewAttr(View view) {
        if (isColor()) {
            view.setBackgroundColor(ResourceManager.getInstance().getColor(attrValueId));
        } else if (isDrawable()) {
            view.setBackgroundDrawable(ResourceManager.getInstance().getDrawable(attrValueId));
        } else if (isMipmap()) {
            view.setBackgroundDrawable(ResourceManager.getInstance().getMipMap(attrValueId));
        }
    }
}

step2、在application中初始化,如:

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        SkinManager.getInstance().init(this, true);
        AttrFactory.addSupportAttr("background", new BackgroundAttr());
    }
}

step3、编写你的BaseActivity,如:

public class BaseActivity extends AppCompatActivity implements SkinChangeListener {
    public SkinInflaterFactory mSkinInflaterFactory;

    @Override
    public void onSkinChanged() {
        mSkinInflaterFactory.changeSkin();
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        mSkinInflaterFactory = new SkinInflaterFactory(this);
        getLayoutInflater().setFactory2(mSkinInflaterFactory);
        super.onCreate(savedInstanceState);
        SkinManager.getInstance().registerSkinChangeListener(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        SkinManager.getInstance().unRegisterSkinChangeListener(this);
    }
}

step4、在布局中标识需要换肤的view:

...
xmlns:skin="http://schemas.android.com/android/skin"
...
  <TextView
     ...
     skin:enable="true" 
     ... />

或者在代码中手动设置需要换肤的view:

                DynamicSkinAttrItem dynamicSkinAttrItem = new DynamicSkinAttrItem(MainActivity.this, holder.tvItem, new TextSizeAttr(), R.dimen.textSize14);
                mSkinInflaterFactory.addItem(dynamicSkinAttrItem);

多个属性需要换肤的view也可以这样设置:

        List<DynamicSkinAttrListItem.SkinAttrItem> skinAttrItemList = new ArrayList<>();
        skinAttrItemList.add(new DynamicSkinAttrListItem.SkinAttrItem(this, new BackgroundAttr(), R.color.colorBackground));
        skinAttrItemList.add(new DynamicSkinAttrListItem.SkinAttrItem(this, new TextColorAttr(), R.color.selector_color));
        skinAttrItemList.add(new DynamicSkinAttrListItem.SkinAttrItem(this, new TextSizeAttr(), R.dimen.textSize14));
        DynamicSkinAttrListItem dynamicSkinAttrListItem = new DynamicSkinAttrListItem(tvDynamic, skinAttrItemList);
        mSkinInflaterFactory.addItem(dynamicSkinAttrListItem);

step5、皮肤包的制作
         1、皮肤包(后缀名为.skin)的本质是一个apk文件,该apk文件不包含代码,只包含资源文件;
         2、在皮肤包工程中(示例工程为create-skin)添加需要换肤的同名的资源文件,直接编译生成apk文件(在build/outputs/apk下),再更改后缀名为.skin即可(防止用户点击安装);
         3、SkinChangeDemo工程rebuild Project后,即可在skin-package目录下获取皮肤包,可以改名为你所需要的名字。
step6、本地皮肤包
         1、在assets下新建一个skin文件夹,将.skin文件放到该文件夹下;
         2、调用SkinManager的静态方法loadAssetSkin,第一个参数是文件名,第二个参数是加载皮肤时的监听(可为null)。

                SkinManager.getInstance().loadAssetSkin("black.skin", new LoadSkinCallback() {
                    ...
                });

注意:同名皮肤包修改其中的资源后需要重新加载需要调用SkinManager的静态方法init,并将其中的第二参数设置为true。
step7、插件式皮肤包
         1、下载皮肤包到手机中(本案例未提供下载方法);
         2、调用SkinManager的静态方法loadSkin,第一个参数是文件位置,第二个参数是加载皮肤时的监听(可为null)。

                SkinManager.getInstance().loadSkin(skinPkgPath, new LoadSkinCallback() {
                    ...
                });

step8、 重置为加载系统的资源
调用SkinManager的静态方法resetDefualtSkin即可。

原理:获取其他app的资源作为自己的resource使用。这里通过自定义Factory并设置给activity,使SkinInflaterFactory在activity解析xml文件创建view初始就收集了该页面上需要换肤的view及其需要改值的属性。还通过mSkinInflaterFactory.addItem(param)来添加在动态创建的view的换肤功能。在换肤时,这里触发给activity添加的监听从而给view的属性重新赋值。在一开始收集view时,ResourceManager就给view赋值了。通过SharedPreferences保存上次使用的是哪个皮肤,在下次打开app时还会是上次的皮肤。通过在application中init将assets中的皮肤资源复制到应用缓存文件中,使其能够用于换肤。
           只要能够收集需要换肤的view,即能达到最终的目的,并不一定需要自定义Factory。这里有份参考,提供了另外的思路。https://github.com/hongyangAndroid/AndroidChangeSkin
 

 

demo地址:https://github.com/1qu212/AndroidSkinChangeDemo
参考:https://github.com/fengjundev/Android-Skin-Loader
           https://github.com/burgessjp/ThemeSkinning
           https://github.com/hongyangAndroid/AndroidChangeSkin

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值