简介
2018年苹果在macOS系统引入了暗黑模式,一经推出广受好评。尤其是我们程序员,经常与代码、文本打交道,亮色风格的界面看久了,眼睛会特别累。有了暗黑模式之后,我们的眼睛终于能被温柔对待了。而且系统内置的应用适配的非常好,拿我们常用的XCode来说,也挑不出什么大毛病。反正我是用了暗黑模式之后就没有回去过了。
当然推出暗黑模式不只是为了程序员准备的,也有其他的原因:
可以当做夜间模式:晚上看屏幕的时候,不会亮到你睁不开眼睛。
信息重点的表达需要:在黑色系更能突出关键信息,能做到一目了然,抓住用户的焦点。
用户审美的需要:有相当多的用户对黑色系的产品很钟爱,当然要迎合他们的需求了。
硬件设备省电的需要:现在流行的OLED屏幕,对于纯黑色像素点是不需要通电的。
其实不管它有多少原因,苹果爸爸这么大力的推广,肯定有它的价值,我们跟着苹果爸爸走的就行。这不iOS13就引入到了iOS系统,对于我们开发者来说,就是又爱又恨啊。如果你们的产品是有格调的产品,多半暗黑模式适配的需求就在路上了,就像我一样。但是最尴尬的地方在于,适配暗黑模式的api只在iOS13可用,你又要让我适配暗黑模式,又要让我最低支持iOS9,你这不是让我为难吗?没办法系统原生支持不了的,那就到咱们的宝藏网站Github上面找一找iOS9+的换肤方案。当然找到了许多,大部分是OC的,因为项目主要语言是Swift,所以pass掉。找到了许多swift三方库,但是里面的一些设计有点过时、有些不支持swift5、有些功能太重了。我只想要一个轻量级、高度自定义的方案即可。没有现成的满足的库,与其委曲求全,不如自己实现。所以就有了方案,一个轻量级、api友好、高度自定义的换肤方案。
该方案主要借鉴了iOS13的暗黑模式适配API,所以建议你先去网上查阅iOS13的暗黑模式适配指南。先对系统的方案有一定了解,再来看你会感到非常亲切。关键在于最低支持iOS9,等于说在iOS9就能使用iOS13的暗黑模式适配方案。而且后面还给出了当你的应用最低支持iOS13时,从切换到系统API的指南。
Github地址
大家可以先进入github地址,看一下效果。JXTheme Github地址
核心代码&关键流程介绍
下面按照换肤API的调用流程来介绍实现方案
1.如何优雅的设置主题属性
通过给控件扩展命名空间属性,类似于的、的,这样可以将支持主题修改的属性,集中到属性。这样比直接给控件扩展属性更加优雅。
核心代码如下:
2.如何根据传入的style配置对应的值
借鉴iOS13系统API。自定义结构体,初始化器为。传入的参数是一个闭包,定义为:。这样就可以针对不同的控件,不同的属性配置,实现最大化的自定义。
核心代码参考第一步示例代码。
3.如何保存主题属性配置闭包
对控件添加属性存储。
核心代码如下:
4.如何记录支持主题属性的控件
为了在主题切换的时候,通知到支持主题属性配置的控件。通过在设置主题属性时,就记录目标控件。
核心代码就是第3步里面的这句代码:
然后它会被记录到的属性里面。因为是,通过弱引用记录控件,所以不存在内存问题。
5.如何切换主题并调用主题属性配置闭包
通过完成主题切换,方法内部再调用被追踪的控件的里面的主题属性配置闭包。
核心代码如下:
预览
preview
特性
√
支持iOS 9+,让你的APP更早的实现;
√
使用命名空间属性:。告别属性扩展用法;
√
使用传入闭包配置。根据不同的完成主题属性配置,实现最大化的自定义;
√
可通过自定义style,不再局限于和;
√
提供属性,作为主题切换的回调入口,可以灵活配置任何属性。不再局限于提供的、等属性;
√
支持控件设置,会影响到其子视图;
√
提供根据配置属性的常规封装、Plist文件静态加载、服务器动态加载示例;
使用示例
扩展添加自定义style
内部仅提供了一个默认的style,其他的业务style需要自己添加,比如只支持和,代码如下:
基础使用
自定义属性配置
配置封装示例
是一个提供主题属性配置的轻量级基础库,不限制使用哪种方式加载资源。下面提供的三个示例仅供参考。
常规配置封装示例
一般的换肤需求,都会有一个UI标准。比如定义三个等级,代码如下:
然后可以封装一个全局函数传入返回对应的配置闭包,就可以极大的减少配置时的代码量,全局函数如下:
主题属性配置时的代码如下:
本地Plist文件配置示例
与常规配置封装一样,只是该方法是从本地Plist文件加载配置的具体值,具体代码参加的类
根据服务器动态添加主题
与常规配置封装一样,只是该方法是从服务器加载配置的具体值,具体代码参加的类
有状态的控件
某些业务需求会存在一个控件有多种状态,比如选中与未选中。不同的状态对于不同的主题又会有不同的配置。配置代码参考如下:
当控件的状态更新时,需要刷新当前的主题属性配置,代码如下:
如果你的控件支持多个状态属性,比如有、、等等,你可以不用一个一个的主题属性调用方法,可以使用下面的代码完成所有配置的主题属性刷新:
overrideThemeStyle
不管主题如何切换,及其子视图的都是
其他说明
为什么使用命名空间属性,而不是使用扩展属性呢?
如果你给系统的类扩展了N个函数,当你在使用该类时,进行函数索引时,就会有N个扩展的方法干扰你的选择。尤其是你在进行其他业务开发,而不是想配置主题属性时。
像、等知名三方库,都使用了命名空间属性实现对系统类的扩展,这是一个更的写法,值得学习。
主题切换通知
根据用户ID存储主题配置
迁移到系统API指南
领取专属 10元无门槛券
私享最新 技术干货