写点什么

优酷暗黑模式(五):暗黑模式的技术实现策略

  • 2020-02-26
  • 本文字数:4964 字

    阅读完需:约 16 分钟

优酷暗黑模式(五):暗黑模式的技术实现策略

正如本系列第一篇文章所介绍的,Google 是从 Android 10 正式发布了对暗黑模式的支持,之前随公众理解的深色氛围一跃而上成为系统平台级能力。暗黑模式带给了我们什么呢?


  • 深色界面在专注环境下与内容有更高的契合度,更凸显内容、缓解视觉疲劳;

  • 深色界面更易营造品质感与沉浸感;

  • 深色界面更易建立填充感。

一、暗黑模式项目背景

暗黑模式作为一种系统平台能力,它打造的是整个用户使用周期的全链路视觉体验,也就是要覆盖到用户能到达的每一个角落。


这包括了分发场景,搜索场景,消费场景等复杂的页面结构,也包括二级落地页,活动页等独立页面; 还包括了弹窗,Toast,播放器等常用组件。要全面覆盖如此复杂细碎的场景,需要实现整体性的视觉呈现效果和低成本的全局平台开关。



分析完暗黑模式的影响范围,我们再来看一下我们实践的对象-优酷 APP。优酷 App 发展到今天,已经从一个单体 App,进化成了一个承载集团众多业务出口的超级 App。所以优酷 App 的页面是由十几个完整建制的内部和外部团队共同开发和维护的。


暗黑模式这种全站范围的适配将涉及到上百位设计/开发/测试同学,管理成本,沟通和协调成本,最终落地成本都非常高。


对于这种全站规格的需求,以往优酷的经验是会大量占用业务需求的开发人力,甚至会因此 delay 部分业务需求。这种开发模式是很难延续,不可接受的,本次暗黑模式的适配,我们既希望在第一时间将暗黑模式呈现给客户的,也希望能以更低的成本来完成项目需求。


这给项目方案提出了很大的挑战,但是得益于优酷之前已经实施了设计标准化体系,因此我们有信心和底气完成这些挑战。

二、暗黑模式在优酷的实践

首先,得益于优酷设计标准化体系的落地,我们已经提炼出公共资源库,构建了多层的 DesignToken 体系; 并对大部分一级页面的业务组件进行了接入。所以我们的工作就变成了两部分,一部分是已经接入设计标准化的视觉元素,这部分可以通过修改公共资源库中的 Token 定义,直接添加对暗黑模式的支持,零成本完成适配。另一部分则是扩大设计标准化体系的覆盖范围,在适配暗黑模式的同时,完成更多业务的技术架构的基础建设。


其次,我们还对于暗黑模式进行了色彩分层,静态色层是全站使用的基础色值,它直接对应着一个具体的值。它不会随着视觉模式的变化而变化。在它之上的是动态色层,动态色在不同的视觉模式下,对应不同的静态色。这是通过 Android 原生的资源加载机制完成: 即暗黑模式对应关系在暗黑资源文件中,普通模式在普通资源文件夹中。


在动态色层之上,是代码编写的色彩管理器,它在合适的时间会去获取当前的所有静态/动态色值。设计这一层有两个原因: 一个是提高性能,提前缓存一份给更上层调用,另一个是形成中间层。


众所周知,XML 资源文件的动态性是不足的。XML 资源启动即加载,加载后就是只读的。有了这一层,我们可以支持服务端动态下发色值 Token 的定义,以达成一定程度的动态性。


在色彩管理器之上,是公共的控件和组件层。有了这样的层次关系,使最终的业务设计可以通过搭建完成,完全不需要从零写起,也不需要关注设计标注的细节,开发再也不用逐个元素的调整,设计也不需要逐个像素的校对。只要在第一次纳入的时候进行一次就可以完成,大幅提高了工作效率。



静态 Token:



动态 Token:


动态色对照表



在实际的适配中,布局文件中需要注意的是要使用 Token 来设置组件属性,而在代码中则可以通过公共资源库中提供的工具方法 UIMode.isDarkMode()来读取当前是否是暗黑模式,通过 ColorConfigureManager.getInstance().getColorMap().get(token 名)来获得色值。


具体的适配工作可以看后面的相关文章。08 暗黑模式在优酷分发场景的落地、09 暗黑模式在优酷消费场景的落地 Android。


下面是暗黑模式适配的示例代码:


<?xml version="1.0" encoding="utf-8"?><com.youku.resource.widget.YKRatioLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="@dimen/resource_size_102"    android:layout_height="@dimen/resource_size_153"    android:gravity="center"    android:orientation="vertical"    app:picRatio="p2s1"    android:id="@+id/yk_item_more_layout"    android:background="@color/ykn_secondary_background">
<com.youku.resource.widget.YKTextView android:id="@+id/yk_item_more" android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/text_view_7b" android:gravity="center" android:drawableRight="@drawable/yk_title_nav_icon" android:text="更多"/></com.youku.resource.widget.YKRatioLinearLayout>

//获取下拉刷新DesignToken色值int refresBgColor = ColorConfigureManager.getInstance().getColorMap().get(YKN_DEEP_BLUE_GRADIENT_MIDDLE_POINT);//设置下拉刷新mYkClassicsHeader.setBgColor(refresBgColor);
//获取顶部导航背景资源,对应android来说都是一个命名,暗黑模式的资源单独放在night目录下int defaultImage = R.drawable.yk_top_bg;//设置顶部导航背景setPlaceHoldForeground(getResources().getDrawable(defaultImage));
//获取页面背景色int backGroundColor=ColorConfigureManager.getInstance().getColorMap().get(YKN_PRIMARY_BACKGROUND);//设置页面背景色setFragmentBackGroundColor();
复制代码


此外,我们在适配暗黑的过程中,还遇到了很多具体的问题,比如

1、低版本 Android 系统如何支持暗黑模式

虽然 Google 是在 Android 10 的版本中才默认添加了暗黑模式的切换开关,但是,在之前的系统版本中已经预埋了对暗黑资源文件夹的加载能力; 而且有一部分厂商如小米就在 Android 9 的 MIUI 定制版本中提供了切换"暗黑模式"的开关。


所以对于低版本的用户,我们也提供了适配方案。具体来说,我们是通过调用系统 API


AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO/MODE_NIGHT_YES);
复制代码


来触发模式切换的。


需要特别注意的是,使用这个函数是有一些坑的。比如,在使用它之后,如果没有在 Activity 的 manifest 文件中增加


android:configChanges=“UIMODE”


的话,在 Activity 转屏也会引起 Activity 重建。


一般的 Activity 开发逻辑可能不会考虑到这种场景,很多逻辑在这里是会引发 Bug 的。

2、如何监视暗黑模式的切换

可以通过 onConfigurationChanged 进行监听。


这里一般有两种情况:


一种是活动需要监听它,来进行手动刷新,这时需要在 manifest 文件增加上面的配置。才能够监听到系统回调。


另一种是某个控件或组件,或者我们的全局状态,可能需要独立监听,这种情况按下面的代码进行监听。


getApplication().registerComponentCallbacks(new ComponentCallbacks() {        @Override        public void onConfigurationChanged(Configuration newConfig) {        //do something        }}
复制代码

3、系统刷新和手动刷新

暗黑模式的切换必然需要重新渲染页面,这里我们分两种刷新方式:


一种是直接交给系统,系统会在切换是重建 Activity 从而引发页面重新渲染。这种适合"用户使用行为不需要记录状态"的 Native 页面,和 Weex/H5 等动态页面。缺点就是会丢失用户之前的视觉锚点。


另一种, 则是自己监听 onConfigurationChanged 事件然后手动进行有目的范围的"局部刷新"。比如优酷 App 中的播放页。请参考《极致酷黑: 优酷暗黑模式实现系列 – (9)暗黑模式在优酷消费场景的落地 Android》

4、设计体系未覆盖的老旧页面如何适配

在众多的页面中,有一些老旧的页面改造成本过高,甚至已无人维护。


如果不作任何处理的话,这些页面会因为同时使用已改造组件和未改造组件而造成不同视觉模式同时出现。为了了避免这种情况的发生,我们会在页面进入时,强制指定页面的视觉模式方法是:


getDelegate().setLocalNightMode(MODE_NIGHT_YES/MODE_NIGHT_NO);
复制代码


这个 API 的作用范围是所属的 Activity。

三、未来的展望

我们认为,设计标准化体系大大的提高了类似"暗黑模式"这种全站视觉变更项目的效率,DesignToken 的设计将开发从繁琐的视觉效果开发中解脱了出来。


优酷的暗黑模式适配在两周之内顺利完成,并且没有影响同期的产品需求。未来我们会继续深化和丰富标准化设计体系的能力,也希望这种开发方式可以在不同的 App 间变成通用的开发范式。


设计标准化体系的开发,对于公共组件池的跨应用使用,Weex/Flutter/小程序等的跨应用通投都有重要的参考意义。


作者简介


涵父,阿里文娱无线开发专家。


相关阅读


优酷暗黑模式(一):是什么、为什么、如何落地?


优酷暗黑模式(二):如何建立设计语言标准化管理体系


优酷暗黑模式(三):暗黑模式设计指南


优酷暗黑模式(四):设计标准化的技术实现


2020-02-26 10:002244

评论

发布
暂无评论
发现更多内容

新能源汽车补贴没了,行业还能快速发展吗?

石云升

学习笔记 新能源汽车 11月日更

中央银行、不平等和新技术:使用分布式账本、可编程合约和密码学的蓝图

CECBC

jodconverter实现在线预览

小鲍侃java

11月日更

架构设计

AHUI

「架构实战营」

一起听、一起看、一起唱掀起Z世代青年社交浪潮

声网

人工智能 算法 音视频

15 K8S之容器安全上下文

穿过生命散发芬芳

k8s 11月日更

一个基于PoS共识算法的区块链案例

Regan Yue

区块链 共识算法 11月日更 细讲区块链

1 分钟学会 30 种编程语言

AlwaysBeta

监管打压加码!虚拟货币挖矿再遭围堵 “漏网之鱼”当休

CECBC

【算法技术专题】如何用Java实现一致性 hash 算法( consistent hashing )(上)

洛神灬殇

算法 一致性hash 11月日更

范学雷的专栏《深入剖析 Java 新特性》

IT蜗壳-Tango

11月日更

华为初面+综合面试(Java技术面)附上面试题,share给大家~

Java 编程 程序员 面试

识别AI换脸!百度这项技术夺冠了!

百度大脑

人工智能 百度

赢在2022,面试官常问的软件测试面试题总结

六十七点五

软件测试 面试题 自动化测试 经验总结 测试工程师

这一次,Google 终于对 Web 自动化下手了!

星安果

chrome 自动化

何止一个惨字形容,水滴Java面试一轮游,壮烈了,问啥啥不会,数据库血崩,我该怎么办?

Java 编程 程序员 面试

你不知道的开源分布式存储系统 Alluxio 源码完整解析(上篇)

腾源会

大数据 开源 数据湖

科技热点周刊|马斯克套现 440 亿;苹果推出数字身份证;Meta 与微软合作;华为捐赠欧拉

青云技术社区

云计算 物联网

你不知道的开源分布式存储系统 Alluxio 源码完整解析(下篇)

腾源会

大数据 开源

在线假单词随机生成器

入门小站

工具

【LeetCode】重新排序得到 2 的幂Java题解

Albert

算法 LeetCode 11月日更

在华为云专属月,找到开启互联网第二增长曲线的一把钥匙

脑极体

NodeJs 深入浅出之旅:V8 内存分配🧙‍♂️

空城机

大前端 Node 11月日更

你现在可以在元宇宙里 “打工”了!

CECBC

请问软件测试和渗透测试的区别是什么?

喀拉峻

网络安全 渗透测试

验证码

卢卡多多

图片验证码 11月日更

直接破防了,阿里大咖DDD(领域驱动设计)不破不立,GitHub直接霸榜,今天share给大家~

编程 程序员 领域驱动

浏览器的几种防护策略

网络安全学海

网络安全 信息安全 渗透测试 WEB安全 安全漏洞

linux下清理系统缓存并释放内存

入门小站

Linux

数据同步:教你如何实时把数据从 MySQL 同步到 OceanBase

OceanBase 数据库

数据库 开源 oceanbase 分布式,

gitlab registry占用存储过大问题解决

ilinux

优酷暗黑模式(五):暗黑模式的技术实现策略_移动_阿里巴巴文娱技术_InfoQ精选文章