1、使用

环境:

Android studio 4.1
gradle:3.4.0+5.4.1

使用的androidx,所以导入的库是

//换肤框架
implementation 'skin.support:skin-support:4.0.5'                   // skin-support
implementation 'skin.support:skin-support-appcompat:4.0.5'         // skin-support 基础控件支持
implementation 'skin.support:skin-support-design:4.0.5'            // skin-support-design material design 控件支持[可选]
implementation 'skin.support:skin-support-cardview:4.0.5'          // skin-support-cardview CardView 控件支持[可选]
implementation 'skin.support:skin-support-constraint-layout:4.0.5' // skin-support-constraint-layout ConstraintLayout 控件支持[可选]

初始化:
在application的oncreate方法中

SkinCompatManager.withoutActivity(this)
//                .addStrategy(new CustomSDCardLoader())          // 自定义加载策略,指定SDCard路径
//                .addStrategy(new ZipSDCardLoader())             // 自定义加载策略,获取zip包中的资源.addInflater(new SkinAppCompatViewInflater())   // 基础控件换肤.addInflater(new SkinMaterialViewInflater())    // material design.addInflater(new SkinConstraintViewInflater())  // ConstraintLayout.addInflater(new SkinCardViewInflater())        // CardView v7
//                .setSkinStatusBarColorEnable(true)              // 关闭状态栏换肤
//                .setSkinWindowBackgroundEnable(false)           // 关闭windowBackground换肤
//                .setSkinAllActivityEnable(false)                // true: 默认所有的Activity都换肤; false: 只有实现SkinCompatSupportable接口的Activity换肤.loadSkin();

使用的activity要重写方法

@androidx.annotation.NonNull
@Override
public AppCompatDelegate getDelegate() {return SkinAppCompatDelegateImpl.get(this, this);
}

恢复的方法:

SkinCompatManager.getInstance().restoreDefaultTheme();

1.1 应用内换肤

皮肤制作:

copy一份res,并命名为res-night
res目录下colorx.xml

<?xml version="1.0" encoding="utf-8"?>
<resources><color name="colorPrimary">#6200EE</color><color name="colorPrimaryDark">#3700B3</color><color name="colorAccent">#03DAC5</color>
</resources>

res-night目录下在colors.xml中

<?xml version="1.0" encoding="utf-8"?>
<resources><color name="colorPrimary_night">#ff5500</color><color name="colorPrimaryDark_night">#00bb00</color><color name="colorAccent_night">#666666</color>
</resources>

上面两个文件的name是一一对应的,只是颜色值不同

在app下的build.gradle中添加

defaultConfig {sourceSets {main {res.srcDirs = ['src/main/res','src/main/res-night']}
}
}

在换肤的地方调用

SkinCompatManager.getInstance().loadSkin("night", SkinCompatManager.SKIN_LOADER_STRATEGY_BUILD_IN); // 后缀加载

1.2 插件化换肤

先制作一个皮肤包,就是创建一个module,内部没有activity,只是把colors.xml中的值和原来app中的一一对应,设置不同颜色

<?xml version="1.0" encoding="utf-8"?>
<resources><color name="colorPrimary">#ff5500</color><color name="colorPrimaryDark">#00bb00</color><color name="colorAccent">#666666</color>
</resources>

打包成apk,放在app下的assets/skins下,并修改后缀为skin

在换肤的地方调用

SkinCompatManager.getInstance().loadSkin("skin-night.skin", SkinCompatManager.SKIN_LOADER_STRATEGY_ASSETS);

2、原理

使用的设计模式就是订阅者模式
使用一个ArrayList<SkinObserver> observers;存储每个页面,等到换肤的时候,遍历每个页面的所有控件,依次将其换肤

public static SkinActivityLifecycle init(Application application) {if (sInstance == null) {synchronized (SkinActivityLifecycle.class) {if (sInstance == null) {sInstance = new SkinActivityLifecycle(application);}}}return sInstance;}private SkinActivityLifecycle(Application application) {application.registerActivityLifecycleCallbacks(this);installLayoutFactory(application);SkinCompatManager.getInstance().addObserver(getObserver(application));}

SkinActivityLifecycle在初始化的时候,application.registerActivityLifecycleCallbacks(this);注册了registerActivityLifecycleCallback实现在每个activity或者fragment页面生命周期进行监听,在onresume方法调用时候将context对象存储到map中,并添加到observers链表中,在ondestroy方法中将其删除。存储observers时候使用了弱引用来进行中间转换,达到优化内存的目的,防止存储数量过大导致oom。存储了每个对象之后,在换肤的时候,只需要遍历observers,设置每个context的背景、主题、内部控件的背景色等,就能实现换肤的目的。

   installLayoutFactory(application);private void installLayoutFactory(Context context) {try {LayoutInflater layoutInflater = LayoutInflater.from(context);LayoutInflaterCompat.setFactory2(layoutInflater, getSkinDelegate(context));} catch (Throwable e) {Slog.i("SkinActivity", "A factory has already been set on this LayoutInflater");}}

创建自己的SkinCompatDelegate代替每个activity创建过程中系统创建的LayoutInflater.Factory2,拦截系统的创建View过程,全部替换成自己的Skin系列控件,在其中添加自己的代码,实现控制View背景的目的;存储SkinCompatDelegate的时候,使用了弱引用来达到优化内存使用的目的

android-skin-support使用和原理分析相关推荐

  1. Android 7.0 分屏原理分析

    在以往的Android系统上,所有Activity都是全屏的,如果不设置透明效果,一次只能看到一个Activity界面. 但是从Android N(7.0)版本开始,系统支持了多窗口功能.在有了多窗口 ...

  2. android uc浏览器的实现原理分析

    先下载个UC客户端 然后把APK的后缀改成压缩格式的rar   然后你把里面的东西都解压出来  如果你的开发经验很OK的话  很快就会看明白. 1:其实UC浏览器并不是什么很难的东西,在国内IT圈里有 ...

  3. 滴滴开源Android插件化框架VirtualAPK原理分析

    概述 滴滴出行公司的首个对外开源项目 - VirtualAPK.地址:github.com/didi/Virtua- 滴滴自行研发了这款插件化框架,功能全面.兼容性好,还能够适用于有耦合的业务插件,这 ...

  4. Android之基于xmpp openfire smack开发之Android消息推送技术原理分析和实践[4]

    http://blog.csdn.net/shimiso/article/details/8156439 前面几篇给大家系统讲解的有关xmpp openfire smack asmack相关的技术和使 ...

  5. Android V1签名与校验原理分析(全网最全最详细)

    [前言] Android Apk V1签名方式是一开始时使用的签名方案,不过V1签名方式也称作Jar签名,顾名思义,就是V1签名并不是Android独有的签名方式,而且在Android还没出来时候,J ...

  6. Android V2签名与校验原理分析

    [前言] V1签名作为一种历史悠久的签名方式,弊端也是比较明显的,一方面由于V1签名是对Apk内的单个文件逐一计算摘要进行签名校验的,所以要是Apk内的文件比较多,计算速度是非常慢的,同时又因为只对单 ...

  7. android instrumentation 原理,Android 运行Instrumentation Test的原理分析

    1. 准备 首先安装被测试程序和包含测试case的程序 包含测试case的程序的AndroidManifest中包含有这么一行配置: 其中targetPackage指定测试程序的包名 2.运行 adb ...

  8. Android性能优化一绘制原理分析

    Android应用启动慢,使用时经常卡顿,是非常影响用户体验的,应该尽量避免出现. 1.卡顿的分类 按照场景分可以分为: UI绘制 绘制 刷新 应用启动 安装启动 冷启动 热启动 页面跳转 页面间切换 ...

  9. Android双屏异显以及原理分析

    副屏显示 android设备可以开启模拟副屏,通过Presentation实现模拟副屏的画面绘制. 进入设置的开发者选项,找到绘图-模拟辅助显示设备(英文为Simulate secondary dis ...

  10. android群聊红包原理,Android之微信抢红包实现原理分析

    微信抢红包主要用到AccessibilityService,该服务需要用户手动到辅助功能里面授权,下面直接粘贴源码,先看Activity,主要是跳转到辅助功能界面,让用户开启辅助功能的服务: publ ...

最新文章

  1. 没有c语言基础可以学python吗-零基础学Python之前需要学c语言吗
  2. ARM微处理器的体系结构
  3. 【BZOJ-2299】向量 裴蜀定理 + 最大公约数
  4. DataAdapter.FillSchema 方法
  5. HTML 页面自动刷新
  6. hdu 6183 线段树的空间优化
  7. JS判断字符串变量是否含有某个字串的方法
  8. 【java】理解和运用Java中的Lambda
  9. 论文Mathtype公式自动编号
  10. 「leetcode」90.子集II【回溯算法】详细图解!
  11. 计算机cpu在哪,cpu什么意思啊_电脑cpu哪里看
  12. 淘宝订单自动确认收货的N种实现,秒杀面试官
  13. 哪个品牌台灯护眼效果好?分享被央视315表扬的护眼灯
  14. python数据汇总_Python,将数据框中的每日数据汇总到每月和每季度
  15. nginx中配置不输入端口(指定地址)访问项目的方法
  16. 【CSharp】延迟初始化(Lazy)
  17. LeetCode/LintCode 题解丨一周爆刷字符串:URL 编码
  18. 【读书笔记】销售运营-策略制定的6大原则及5个常用工具
  19. msdn i tell you网址及下载系统详细步骤
  20. tf2 + keras学习

热门文章

  1. 【清风数学建模笔记】第七讲 多元回归分析
  2. ubuntu安装darknet
  3. 【源码分析】redux-thunk
  4. 盘点最高调薪行业 年薪过万要几年
  5. DoodleJump
  6. python下拉框二级联动_下拉列表框实现二级联动
  7. 我的创业日记(序)——人生在于一种体验
  8. Redis的安装及测试
  9. 显示分辨率和图像分辨率_如何用任何图像制作高分辨率Windows 7图标
  10. Nature | 江西农大黄路生/陈从英等揭示猪血型基因调控肠道菌群的机制