android-skin-support使用和原理分析
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使用和原理分析相关推荐
- Android 7.0 分屏原理分析
在以往的Android系统上,所有Activity都是全屏的,如果不设置透明效果,一次只能看到一个Activity界面. 但是从Android N(7.0)版本开始,系统支持了多窗口功能.在有了多窗口 ...
- android uc浏览器的实现原理分析
先下载个UC客户端 然后把APK的后缀改成压缩格式的rar 然后你把里面的东西都解压出来 如果你的开发经验很OK的话 很快就会看明白. 1:其实UC浏览器并不是什么很难的东西,在国内IT圈里有 ...
- 滴滴开源Android插件化框架VirtualAPK原理分析
概述 滴滴出行公司的首个对外开源项目 - VirtualAPK.地址:github.com/didi/Virtua- 滴滴自行研发了这款插件化框架,功能全面.兼容性好,还能够适用于有耦合的业务插件,这 ...
- Android之基于xmpp openfire smack开发之Android消息推送技术原理分析和实践[4]
http://blog.csdn.net/shimiso/article/details/8156439 前面几篇给大家系统讲解的有关xmpp openfire smack asmack相关的技术和使 ...
- Android V1签名与校验原理分析(全网最全最详细)
[前言] Android Apk V1签名方式是一开始时使用的签名方案,不过V1签名方式也称作Jar签名,顾名思义,就是V1签名并不是Android独有的签名方式,而且在Android还没出来时候,J ...
- Android V2签名与校验原理分析
[前言] V1签名作为一种历史悠久的签名方式,弊端也是比较明显的,一方面由于V1签名是对Apk内的单个文件逐一计算摘要进行签名校验的,所以要是Apk内的文件比较多,计算速度是非常慢的,同时又因为只对单 ...
- android instrumentation 原理,Android 运行Instrumentation Test的原理分析
1. 准备 首先安装被测试程序和包含测试case的程序 包含测试case的程序的AndroidManifest中包含有这么一行配置: 其中targetPackage指定测试程序的包名 2.运行 adb ...
- Android性能优化一绘制原理分析
Android应用启动慢,使用时经常卡顿,是非常影响用户体验的,应该尽量避免出现. 1.卡顿的分类 按照场景分可以分为: UI绘制 绘制 刷新 应用启动 安装启动 冷启动 热启动 页面跳转 页面间切换 ...
- Android双屏异显以及原理分析
副屏显示 android设备可以开启模拟副屏,通过Presentation实现模拟副屏的画面绘制. 进入设置的开发者选项,找到绘图-模拟辅助显示设备(英文为Simulate secondary dis ...
- android群聊红包原理,Android之微信抢红包实现原理分析
微信抢红包主要用到AccessibilityService,该服务需要用户手动到辅助功能里面授权,下面直接粘贴源码,先看Activity,主要是跳转到辅助功能界面,让用户开启辅助功能的服务: publ ...
最新文章
- 没有c语言基础可以学python吗-零基础学Python之前需要学c语言吗
- ARM微处理器的体系结构
- 【BZOJ-2299】向量 裴蜀定理 + 最大公约数
- DataAdapter.FillSchema 方法
- HTML 页面自动刷新
- hdu 6183 线段树的空间优化
- JS判断字符串变量是否含有某个字串的方法
- 【java】理解和运用Java中的Lambda
- 论文Mathtype公式自动编号
- 「leetcode」90.子集II【回溯算法】详细图解!
- 计算机cpu在哪,cpu什么意思啊_电脑cpu哪里看
- 淘宝订单自动确认收货的N种实现,秒杀面试官
- 哪个品牌台灯护眼效果好?分享被央视315表扬的护眼灯
- python数据汇总_Python,将数据框中的每日数据汇总到每月和每季度
- nginx中配置不输入端口(指定地址)访问项目的方法
- 【CSharp】延迟初始化(Lazy)
- LeetCode/LintCode 题解丨一周爆刷字符串:URL 编码
- 【读书笔记】销售运营-策略制定的6大原则及5个常用工具
- msdn i tell you网址及下载系统详细步骤
- tf2 + keras学习