第一种方式就是简单,但是它有两个弊端:
- Dark Mode 切换时,它需要重建整个
Activity
,一般情况还好,你感知不到重建这个过程,但是如果View
特别大,单单创建 View 就非常耗时了,那么就会明显感知到黑屏(很多产品喜欢把界面逻辑搞得特别复杂,例如ViewPager
嵌套ViewPager
, 再嵌套ViewPager
, 而且每个 Pager 都还巨复杂) - 另外一点就是,既然已经支持一套皮肤,为何不能多支持几套?例如全黑白版(伪墨水屏)
因此,QMUI 推荐采取第二种方式,因此 QMUI 提供了换肤功能的支持,夜间模式只是在 onConfigurationChanged
时调用一下换肤接口而已。 当然,开发者也可以创建 *-night 文件夹,并在里面配置 qmui 的各种 color/drawable 设置,以第一种方式去完成夜间模式的适配。 QMUI 只是将组建资源取值 Attr 化,使用何种方式,都是由使用者自己决定。
常规使用方式, 在 Application.onCreate()
里加入你的 skin 支持项:
QMUISkinManager skinManager = QMUISkinManager.defaultInstance(this);
skinManager.addSkin(1, R.style.app_skin_blue);
skinManager.addSkin(2, R.style.app_skin_dark);
skinManager.addSkin(3, R.style.app_skin_white);
skinManager.changeSkin(isDarkMode ? 2 : 1);
R.style.app_skin_blue
、R.style.app_skin_dark
、R.style.app_skin_white
等就是不同 skin 下的配置, 然后在 Application.onConfigurationChanged
里监听 uiMode
的信息:
if((newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES){
QDSkinManager.changeSkin(QDSkinManager.SKIN_DARK);
}else if(QDSkinManager.getCurrentSkin() == QDSkinManager.SKIN_DARK){
QDSkinManager.changeSkin(QDSkinManager.SKIN_BLUE);
}
当然,对于启动 LauncherActivity
的背景,是没有机会走到 QMUI 的换肤机制的,因此要退化到第一种 Dark Mode 的实现方案。
那么业务上我们如何对 View
来设置呢? 有以下方式:
- 如果你采用的是 xml, 可以通过 QMUI 提供的
qmui_skin_xxx
的设置项来设置你 skin。 - 如果你想在 java 代码中设置 skin, 那么需要采用
QMUISkinValueBuilder
来构建 value, 再通过QMUISkinHelper.setSkinValue
来设置,稍显复杂,如果通过是 kotlin 的话,QMUI 提供了View.skin
方法,可以快速实现。 - 还有一种尚在开发的方式, 我把它叫做
skin-maker
。 目的是可以让设计师通过点点点的方式进行 skin 设置,然后导出一份配置文件,放到工程里,通过字节码注入完成 skin 设置,这样可以将整个配置工作交给设计,不用每做个新业务都要考虑换肤。 理想是美好的,现实是目前做了一个 Demo 版,有兴趣的可以在 QMUIDemo 上体验体验,流程是通的,但还有很多问题没解决。
QMUIPopup 重写
QMUIPopup 之前的实现是比较糟糕的,采用了 .9.png 的方式实现了背景阴影,因为阴影是占位置的,所以边缘距离过大,如果 anchorView 在很边缘的位置,会出现箭头错位或者显示不理想的情况,很多人踩了这个坑,而解约方案只能是提供一个阴影小一点的背景图。
因此,这个版本完全重写了它,采用了 QMUILayout 的方式实现阴影,所以你想完全贴边也是可以的。 除此之外, 2.x 版本提供了 QMUIQuickAction
和 QMUIFullScreenPopup
, 前者样式来源于微信读书阅读器的快捷菜单,当然实现不一样(虽然微信读书上的那个也是我写的,但是当年的实现,不忍直视)。 后者可以用于实现微信读书各种想法浮层,去年读书各种浮层兴起,并且还有键盘交互,我算是有一些心得吧,也提取了出来。
一个简单的使用例子:
QMUIPopups.popup(getContext(), QMUIDisplayHelper.dp2px(getContext(), 250))
.preferredDirection(QMUIPopup.DIRECTION_BOTTOM)
.view(textView)
.edgeProtection(QMUIDisplayHelper.dp2px(getContext(), 20))
.offsetX(QMUIDisplayHelper.dp2px(getContext(), 20))
.offsetYIfBottom(QMUIDisplayHelper.dp2px(getContext(), 5))
.shadow(true)
.arrow(true)
.animStyle(QMUIPopup.ANIM_GROW_FROM_CENTER)
.onDismiss(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
Toast.makeText(getContext(), “onDismiss”, Toast.LENGTH_SHORT).show();
}
})
.show(v);
组织形式比以前的舒服多了吧。
更多修改
当然,除了 QMUIPopup 的重写,其它组件也都有很大的改动:
- QMUITabSegment 大面积重写,提供了两张图片切换、不同 Tab 不同设置等功能,扩展也更加灵活。
- QMUIBottomSheet.BottomListSheetBuilder 添加了很多人期待的居中设置
- QMUICommonListItemView 更改父类为 ConstraintLayout, 重写布局,可以设置高度 wrap_content 以支持超长标题或副标题
- 提供了 QMUISlider 组件
- …
最后,目前的版本没有经过充分的测试和实践,可能会存在比较多的问题,欢迎大家提 issue 。
原本链接: blog.cgsdream.org/2019/12/01/…
尾声
开发是需要一定的基础的,我是08年开始进入Android这行的,在这期间经历了Android的鼎盛时期,和所谓的Android”凉了“。中间当然也有着,不可说的心酸,看着身边朋友,同事一个个转前端,换行业,其实当时我的心也有过犹豫,但是我还是坚持下来了,这次的疫情就是一个好的机会,大浪淘沙,优胜劣汰。再等等,说不定下一个黄金浪潮就被你等到了。
- 330页 PDF Android核心笔记
- 几十套阿里 、字节跳动、腾讯、华为、美团等公司2020年的面试题
- PDF和思维脑图,包含知识脉络 + 诸多细节
- Android进阶系统学习视频
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
37427)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!