前言
随着一款APP应用功能的不断完善,用户群体的不断增多,APP的更新也就不仅仅局限于功能需求,如何做好良好的用户体验,让用户传播良好的体验口碑,显得尤为重要,而用户体验一块日夜间模式俨然成为了标配。其实,日夜间功能就是换肤的一种,关于换肤功能的实现,也是众说纷纭,总的来讲分为两类:主题换肤(Theme)和插件换肤(APK换肤)。
插件换肤
插件换肤的实现原理就是主APK根据当前环境需求,解析指定目录下对应的插件APK,获得其中同名的资源文件并动态替换到主APK的应用程序中。插件APK并不需要安装,只需要放置在指定目录下即可。
- 优点: 能够实现各种主题样式的加载,比较灵活,需要增添新的主题只要新建一个插件APK,并配置好相关的资源,放置到指定的文件目录下就行,很方便。
- 缺点: 需要对控件进行适配修改,实现换肤功能,对于自定义控件,也需要在适配上花点时间。而且放置在文件夹中的插件APK也可能会因为被误删或是损坏而造成资源获取不到,导致换肤失败。
主题换肤
主题换肤的实现原理就是在主apk配置多套主题,每套主题对同一个属性使用相应的资源。
- 优点: 相比插件换肤来说更容易上手,理解起来也会更容易。
- 缺点: 增添新的主题样式必须要发布新版本。全部资源文件都放在APK中,APK会显得十分臃肿,特别是图片资源,因此个人推荐纯色线条的图标,并通过着色来实现不同主题下换肤的可能。
因为今天的主题是日夜间模式,考虑到并不会涉及主题样式增添的可能,所以权衡之下还是选择使用主题换肤来实现日夜间模式,老套路,效果预览(文末将附上高清地址入口)
准备相关的属性样式及主题:
自定义attr属性:
主题换肤和插件换肤原理其实一样,就是控制不同模式下加载对应的资源文件,只是实现的方式不同而已。以往我们在写xml布局文件的时候,默认的属性赋值都是绝对的,即android:background="#FFFFFF"
或android:background="@color/white"
。
而一旦属性被这样赋值,默认的资源加载就被限制,倘若有需求需要视图在加载时能够根据当前环境配置特定的资源,那就只能在Java程序代码中动态修改,繁琐程度可想而知。那么是否一个办法能够使xml属性的赋值能够动态的根据当前主题样式的改变而去加载默认的资源呢 ?
有,那就是今天的腕儿:自定义属性。在我看来自定义属性在主题换肤中充当着占位符的角色,它会告诉系统这是一个相对的引用,真正的资源引用是当前上下文环境所对应的主题样式属性列表中,对这个自定义属性的赋值。
1.在res-value目录下新建attr属性的资源文件,例如:custom_theme_attrs.xml
。
2.在custom_theme_attrs.xml
文件中新建自定义属性。
格式:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="自定义属性名称" format="资源引用格式(color、dimen、reference...)" />
</resources>
示例:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 控制app背景色 format:颜色值、资源引用 -->
<attr name="custom_attr_app_bg" format="color|reference" />
<!-- 控制app标题栏背景色 format:颜色值、资源引用 -->
<attr name="custom_attr_app_title_layout_bg" format="color|reference" />
<!-- 用户头像显示占位Drawable format:颜色值、资源引用 -->
<attr name="custom_attr_user_photo_place_holder" format="color|reference" />
<!-- 用户昵称字体颜色 format:颜色值、资源引用 -->
<attr name="custom_attr_nickname_text_color" format="color|reference" />
<!-- 用户备注字体颜色 format:颜色值、资源引用 -->
<attr name="custom_attr_remark_text_color" format="color|reference" />
<!-- 用户头像显示的透明度 format:尺寸值、资源引用 -->
<attr name="custom_attr_user_photo_alpha" format="dimension|reference" />
</resources>
写过自定义View的朋友一定不会陌生,不就是自定义属性嘛。区别就是这些属性值没有包裹在styleable
中,至于为啥我就不班门弄斧,有需要的朋友可以了解简书作者楚云之南写的《深入理解Android 自定义attr Style styleable以及其应用》,感觉写的不错,感谢分享 !!