应用换肤是常见的需求了,项目工程需要将设计资源的颜色、字体、图片等设计元素使用皮肤文件进行配置管理。本方案主要以项目支持马甲包资源管理、样式配置为主。
核心需求点:
马甲包开发支持,方便马甲包进行样式配置(区分)及资源包集成;
皮肤包功能,支持动态下载皮肤包(比如节日包),并应用到App上;
皮肤热更新,支持后台推送、App实时更新样式;
优先支持需求点1、2,需求点2、需求点3需后台配合支持。
代码开发快速上手请见「[配置格式说明]」及「[快速上手]」。代码仓库在HTSkinBundle。
样式配置
配置格式说明
目前使用json作为配置文件格式。
目前暂定,应用全局配置使用主皮肤包中的appstyle.json,业务配置可自定somemodule.json。应用全局配置具有较为固定的key、默认会在App启动后读取配置应用到全局UI上,业务配置按需自定。
分割为多个配置文件,一则减少单次IO访问阻塞时间,二则隔离各业务配置、减少冲突。
以下为示例配置文件。每个key是业务id,也就是带义务意义的key。单个配置文件内应保证key的唯一性。
1 | { |
颜色配置格式
颜色的配置格式包括三种:
String
纯色配置。支持#RGB、0xRGBA、#RRGGBB、RRGGBBAA等格式的颜色配置,与UIColor+YYAdd.h保持一致。通常情况默认使用#RRGGBB即可。
1 | { |
因UI规范未定,后续可能有变动。
Object
渐变色配置。主要包括3个key的配置:
colors
:Array
,元素同上述1的String
格式locations
:Array
,元素为Float格式,取值范围[0, 1]style
:Int
,可选0/1/2/3,请参考GradientStyle的取值,可拓展。
属性意义可参考CAGradientLayer。
1 | { |
Array
渐变色配置,即第2种格式的简化版,只使用colors进行配置。默认locations为均分,即均匀渐变,style为GradientStyleLeftToRight。
字体配置格式
字体的配置格式包括三种:
Float
通过字号配置,将使用皮肤包「全局配置」中的字体(或系统字体)。
⚠️请注意是Float格式,若配置为String格式,运行期Debug模式会断言失败、提示修改。
1 | { |
Object
可指定三个key进行配置:
fontName
:String
字体名称fontSize
:Float
字号大小,必选fontWeight
:String
字重,可选:light/regular/medium/semibold/bold
请注意fontSize
为必要的配置。若不提供fontName
则同上述1处理。
1 | { |
⚠️请注意fontWeight
字重仅为系统字体提供,约等同于[UIFont boldSystemFontOfSize:$size]
此类用途。
String
提供便捷的配置格式,字体名称及字号大小,以逗号,分割,示例如”PingFangSC-Medium,16”。
⚠️请注意需要名称、字号同时配置,如仅配置”16”字号会断言失败。
默认情况下,App使用皮肤包配置的全局字体,因此业务如无特别需求,使用第一种方式指定字号即可。
图片配置格式
图片的配置目前仅一种,key: imageName
。
其他配置
其他不属于资源配置,但可能增加接口支持的,比如某些常见的UI控件的配置属性,主要是统一、方便使用。
待定。
全局样式配置
全局样式主要包括App主色、默认字体、导航栏等全局性页面容器等外观配置。
App主色
对应视觉UI规范的主色配置,配置文件中由primaryColor指定,纯色。
App默认字体
配置文件中的primaryFont进行指定。支持加载皮肤包携带字体,指定字体名称以在App中全局配置使用(代码需配置),比如可以从PingFang字体切换为自定义字体等。
请确保字体为系统字体,或App内置字体,或皮肤包内置字体。皮肤包内置字体可通过”appstyle.json”配置fonts指定需加载的字体文件。
皮肤包加载时,默认会搜索皮肤包中ttf后缀的字体进行加载。
若不指定primaryFont,则使用系统默认字体。
导航栏
导航栏的视觉配置,主要包括:(待定)
导航栏背景色/图片:
navigationColor
、navigationBgImage
导航栏标题颜色:
navigationTitleColor
导航栏标题字体:
navigationTitleFont
导航栏返回按钮图片:
navigationBackImage
见下方json配置文件定义。
tabBar
tabBar的视觉配置,主要包括:(待定)
tabBar背景色/图片
tabBar文案字体
tabBar文案颜色
建议修改或开发TabBarController,以支持由内容页面提供响应tab的tabBarIcon图片及文案。
皮肤包中全局配置文件(appstyle.json)
1 | { |
registerFonts
是配置需要动态注册的字体。也可不配置,程序可配置自动搜索皮肤包中的ttf字体文件进行加载。
全局配置文件支持拓展,但通常情况会进行字段限定(比如与设计出的规范文档对齐),并保持稳定。
业务定制样式配置
默认支持(或可支持)UIView及常见控件的样式属性可配置。特殊需支持的配置需求,需要控件支持配置,如未支持需安排开发。
目前GradientButton
、GradientLabel
已提供渐变背景、渐变文字支持。
皮肤包资源构成
皮肤包的配置及资源,在HTSkinBundle
组件中可以配置在Assets
目录下。
如下图示是以项目区分的资源构成:
1 | ├── Assets |
资源
皮肤资源包括字体文件(ttf)、图片(png/jpg)、图片集xcassets、Lottie资源、音频mp3,以及皮肤包的配置文件,都属于皮肤包资源。
目前支持集成的文件后缀包括:xib,png,xcassets,svg,ttf,json,xml,plist,mp3。如果新增需要更新皮肤包组件描述。
共有资源
考虑到目前项目间可能存在大量相同的资源,资源包支持在将其放置在Common目录下,目录结构及文件类型支持保持一致。非必要配置。
项目特有资源
皮肤包工程可自定义项目资源目录,现有App1/App2/App3等(如上目录结构树所示)。
皮肤包最终会以Skin.bundle
资源包的形式集成到主项目中,一般情况下在.app
路径下。
图片可以添加在xcassets
资源集或images
目录下。images
目录可以划分目录管理图片资源。
皮肤包集成
基于pod组件进行集成。使用方式说明请见「快速上手」部分。
主皮肤包
跟随HTSkinBundle
进行集成即可。
组件资源包
此组件,特指项目的Component
类组件,通常为业务组件。业务组件如需要区分马甲包进行样式配置,可以添加配置文件到组件资源包中,业务上使用方法除指定component外几乎一致。
若业务组件需要区分资源包,请业务组件自行安排集成,比如通过subspec方式来区分项目集成亦可。
皮肤包更新
需要将主皮肤包映射到沙盒中。支持全量更新或增量更新,具体策略,涉及资源包版本管理、补丁包制作及更新包等细化逻辑。以下说明方案思路。
资源包更新
管理后台
管理后台支持资源包上传(托管)、版本化及差分包生成等。主要为后端内容,差分/补丁制作工具与客户端保持统一即可,此处不赘述。
皮肤包版本约束包括主应用最低版本要求、主皮肤包版本、差分包版本及对应主皮肤包版本等版本信息。
全量更新
主要流程:
皮肤包zip上传到文件托管服务;
客户端与后台进行配置版本同步,同步策略两端协商即可。比如可以App定期启动后拉取配置版本,也可以服务端推送或其他手段进行同步;
客户端版本比对能力,客户端按需下载皮肤包文件;
客户端更新皮肤包映射关系,触发皮肤热更新等;
增量更新
增量更新包括两部分:差分包(补丁包)制作、差分包应用(集成)。
- 差分包制作
差分包的制作需要使用diff工具,具体的选择看需要。目前bsdiff和bspatch是一套常用的工具,可以参考使用。考虑进一步性能优化情况下,可再考虑其他diff工具的组合使用。
- 差分包集成
通常是阶梯式进行diff应用。
客户端在拉取到皮肤包配置后,根据应用版本及资源版本自行判断是否适用全量更新或增量更新;
确定增量更新后,递归下载所需的增量包;
递归、阶梯式应用增量包到全量包生成新的全量包,直到生成目标资源包结束;
客户端更新皮肤包映射关系,并触发皮肤热更新。
皮肤热更新
包含两部分:
- 热切换
主要是指客户端需要支持配置更新(全部或个别)后,在App侧能直接生效。具体实现方式,可通过观察者模式或闭包缓存的方式实现。
对业务开发使用无影响。
- 热更新
主要是指客户端需要及时获知配置及资源包的更新,比如轮询,比如服务端推送等多种手段都可实现,此处亦不赘述。
快速上手
- Podfile添加依赖HTSkinBundle
默认集成项目的资源包,相关项目或希望调试其他资源包时,需指定对应的subspec
1 | pod 'HTSkinBundle' |
或有需要可以将资源包抽离为独立的pod组件,将资源托管到静态服务。
- 使用支持配置的控件
1 | import HTSkinBundle |
Swift版的接口,控件的可配置属性约束在style
的域下所支持的属性。
目前对UIView
、UILabel
等基础控件进行属性配置的支持(持续更新中)。
定制配置目前主要包括GradientButton
及GradientLabel
主要提供渐变背景及渐变文字的支持。
Comments