优酷暗黑模式(八):分发场景落地(Android & iOS)

2020 年 2 月 27 日

优酷暗黑模式(八):分发场景落地(Android & iOS)

一、背景介绍

随着 Android 10 与 iOS 13 先后支持暗黑模式,优酷客户端在完成了架构统一和组件标准化的工作之后,分发场景的复杂业务可以基于统一的技术方案进行暗黑模式的适配。

二、业务介绍

由于优酷业务分发场景业务复杂,承载页面众多 (二十多种),在落地暗黑模式前,我们对优酷分发场景的业务进行了梳理,大致可以分为三类:

第一类是固定入口的页面,比如首页、频道、Feed 流、二级页,它们承接了分发场景的大部分业务,拥有样式丰富的组件库,它们的共性非常高。

第二类是独立业务方开发的二级页,这些二级页由垂直业务团队维护。由于优酷客户端已完成架构统一和组件标准化的工作,各个业务团队适配暗黑模式都是基于同一套技术方案,适配就变成了一个标准化的工作。业务团队只需按统一的方式适配即可,极大提高了开发效率。

第三类是一些历史遗留的一些老页面,这些页面没有固定的入口,入口分散在各个页面和各个组件, 适配暗黑模式成本相对较高。

这样的页面可以有两种处理方式:

  1. 流量小,非核心的分发场景,面临下线的业务不进行暗黑模式的适配。

  2. 有业务价值的页面进行迁移或合并,统一用新版的二级页承载。

三、暗黑适配

页面展现分几种状态:转场态, 加载态 (Loading), 展现态,异常态。暗黑模式适配的主要工作是适配页面的展现态;转场态和加载态的生命周期虽然很短,但是不能忽略,否则很容易出现亮色 - 暗色页面状态的切换,会破坏整体的沉浸式浏览体验,异常态也是因为类似原因不能忽略。

1、页面级别

1) 顶部 / 底部导航 / 容器

顶部导航支持换背景色;底部导航支持换图片资源、文字颜色、背景颜色;容器支持背景色。

Android 示例代码

复制代码
// 获取下拉刷新 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();

iOS 示例代码

复制代码
/// 暗黑变化回调
/// @param manager 当前的主题管理对象
/// @param identifier 当前主题的标志
/// @param theme 当前主题对象
- (void)ykn_themeDidChangeByManager:(YKNThemeManager *)manager identifier:(__kindof NSObject<NSCopying> *)identifier theme:(__kindof NSObject *)theme {
[super ykn_themeDidChangeByManager:manager identifier:identifier theme:theme];
// 顶部渐变色:深蓝渐变顶部 Token
CGColorRef topCGColor = UIColor.ykn_deepBlueGradientTopPoint.CGColor;
// 底部渐变色:深蓝渐变底部 Token
CGColorRef midCGColor = UIColor.ykn_deepBlueGradientMiddlePoint.CGColor;
if (topCGColor && midCGColor) {
_gradientLayer.colors = @[(__bridge id)topCGColor,
(__bridge id)midCGColor];
}
}

2) 页面 / 卡片 / 图片打底色

这里是比较容易遗漏的,Loading 态,错误态,打底图都需要适配,否则页面容易出现“白块”影响整体暗黑效果。

Android 示例代码

复制代码
// 从颜色管理器中取出背景色 YKN_PRIMARY_BACKGROUND 为 Design Token 定义的色值
int bgColor=ColorConfigureManager.getInstance().getColorMap().get(YKN_PRIMARY_BACKGROUND)
setFragmentBackGroundColor(bgColor);

加载骨架图通过 Android 系统的资源寻址自动获得。

我们只需建立暗黑模式的资源目录 (night),并把骨架图的 drawble 放进去即可。

iOS 示例代码

复制代码
// Feed 流 Loading 图通过动态资源方式获取
itemView.image = [UIImage ykn_home_feed_loading_default];
/// 首页 Feed 流默认 Loading 图
+ (UIImage *)ykn_home_feed_loading_default {
return [UIImage ykn_imageWithThemeProvider:^UIImage * _Nonnull(__kindof YKNThemeManager * _Nonnull manager, NSString * _Nullable identifier, NSObject<YKNThemeProtocol> * _Nullable theme) {
// 暗黑模式下的图
if ([identifier isEqualToString:YKNThemeIdentifierDark]) {
return [UIImage imageNamed:@"home_feed_loading_default_d"] ;
}
// 浅色模式下的图
return [UIImage imageNamed:@"home_feed_loading_default"];
}];
}

3) 暗黑与氛围 / 换肤的兼容问题

优酷分发场景支持换肤、氛围和暗黑模式,优先级为氛围 > 换肤 > 暗黑。所有页面、组件都在此规则上进行适配。

a) 页面同时存在氛围 + 暗黑

电影频道为了培养频道用户的心智,定义了头部和轮播的氛围色。

b) 页面整体都是氛围

高清频道突出高清适配的质感,将整个高清频道页面都定义了氛围色。

2、组件级别

分发场景有几十种组件,大部分组件接入非常便捷,只需将引用的资源字段改为 DesignToken 即可;

1) 常规组件

这里 Android 和 iOS 实现有些差异,需要分别说明。

a) Android

Android 为了提高性能,有些文本绘制使用了自定义 View 来单独绘制文本,目的是减少 View 数量和减少 View 的 measure 时间,上图的 PhoneCommonTitlesWidget 就是一个封装了标题绘制的自定义 View。

下面的代码主要是说明了如何使用 DesignToken,使用 DesignToken 色值有两种方式。

第一种,通过 Layout 布局文件使用包含 DesignToken 的 Style,这种方式方式一般用于系统控件,或继承自系统控件的简单封装比如 YKTextView:

复制代码
<com.youku.resource.widget.YKTextView
android:id="@+id/title_context_1"
style="@style/text_view_1a" //style
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="start|center_vertical"
android:layout_marginLeft="@dimen/dim_6"
app:layout_goneMarginLeft="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/title_left_icon"
/>
<style name="text_view_1a">
<item name="android:textSize">@dimen/font_size_big1</item>
<item name="android:textStyle">bold</item>
<item name="android:singleLine">true</item>
<item name="android:includeFontPadding">false</item>
<item name="android:ellipsize">end</item>
<item name="android:textColor">@color/ykn_primary_info</item> //DesignToken 颜色
</style>

第二种,通过代码使用 DesignToken 色值,这种一般是自定义 View 通过 draw 的方式来渲染 UI,比如上图中的 PhoneCommonTitlesWidget。

复制代码
Resources res = context.getResources();
// 主标题字体 size
int sDefaultTitleTextSize = res.getDimensionPixelSize(R.dimen.font_size_middle1);
// 副标题字体 size
int sDefaultSubtitleTextSize = res.getDimensionPixelSize(R.dimen.font_size_middle4);
// 主标题 DesignToken 颜色
int sDefaultTitleTextColor = res.getColor(R.color.ykn_primary_info);
// 副标题 DesignToken 颜色
int sDefaultSubtitleTextColor = res.getColor(R.color.ykn_tertiary_info);

b) iOS

有些组件业务逻辑复杂、视图的层级很深,找到相应的代码非常耗时,我们可以使用 Xcode 的 Debug 工具、也可以使用优酷开发的一套 UI 检查工具 (啄木鸟),来快速适配暗黑模式。

复制代码
// 标题: 一级信息色 Token
_titleLabel.textColor = [UIColor ykn_primaryInfo];
// 子标题: 二级信息色 Token
_subtitleLabel.textColor = [UIColor ykn_secondaryInfo];
// 边框: 升起的一级组块背景 Token
_borderView.backgroundColor = [UIColor ykn_elevatedPrimaryBackground];

2) 特殊组件

优酷有些组件展示的主体是服务端下发的图片,但是服务端暂时不支持下发视频暗黑模式的图片。针对这种组件就需要有个降级策略,尽量保证暗黑模式的整体显示效果,这种属于特例情况要根据自己的业务特性来定义降级模式。

下面是一个具体的样例。

四、遇到的问题

1、Android

由于资源 (color,drawable) 是通用的,对于那些没有适配暗黑的页面要进行特殊处理。具体方式是: 在暗黑模式下进入没有适配暗黑的页面, 需要关闭暗黑模式来保证页面可以寻址到亮色的资源,在离开的时候再恢复暗黑模式。

在进入页面的时候关闭暗黑模式,Activity OnResume 中调用下面代码,关闭暗黑模式

复制代码
// 判断当前是否处在暗黑模式
if (UIMode.getInstance().isDarkMode()) {
// 关闭暗黑模式
appCompatActivity.getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_NO);
// 更新颜色配置
ColorConfigureManager.getInstance().onConfigureChanged();
}

在离开或页面不可见时候恢复暗黑模式,Activity OnPause 中调用下面代码,恢复暗黑模式

复制代码
// 判断当前是否处在暗黑模式
if (UIMode.getInstance().isDarkMode()) {
// 恢复暗黑模式
appCompatActivity.getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
// 关闭暗黑模式
appCompatActivity.getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
// 更新颜色配置
ColorConfigureManager.getInstance().onConfigureChanged();

2、iOS

  1. 渐变色处理方式不友好

iOS 上渐变色无法自动切换暗黑样式,只能通过监听暗黑模式变化通知,手动设置暗黑渐变样式。

  1. 对比系统原生暗黑

五、适配效果

六、总结

暗黑模式对于视频类应用可以明显提升用户体验,在观感上更适合沉浸式的深度浏览,对于夜晚使用能有效避免亮色模式“刺眼”, 对眼睛更加舒适。因为 LED 屏幕在显示黑色像素的时候并不发光,因而可以提升续航时间,看剧更持久。

用户主路径涉及到的页面,弹窗,甚至图片默认打底图,Loading 图,页面加载出来前的骨架图尽量都适配暗黑模式。由于人眼对由暗到亮比由亮到暗更敏感(例如: 黑夜中突然的车灯会晃得睁不眼睛),主业务场景的暗黑模式尽量避免亮色模式的 UI 元素带来视觉反差,破坏用户沉浸式浏览观看体验。

对于 Android 而言,暗黑模式在系统级的支持是从 Android 10 开始,目前 Android 10 的手机还没有大规模的系统升级。在开发中我们可以通过代码强制打开暗黑模式,方便进行开发。产品上也可以考虑在客户端的设置项中增加“强制暗黑模式”的开关,使得低于 Android 10 版本的手机也可以使用暗黑模式。

作者简介

叔平,阿里文娱无线高级开发工程师。

相关阅读

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

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

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

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

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

优酷暗黑模式(六):暗黑模式的技术支撑 iOS

优酷暗黑模式(七):暗黑模式的技术支撑 Weex & H5

2020 年 2 月 27 日 15:00 644

评论

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

usdt承兑商支付系统开发源码,区块链支付搭建

WX13823153201

Nginx 整合 FastDFS 实现文件服务器

哈喽沃德先生

nginx 文件系统 分布式文件存储 fastdfs 文件服务器

JavaScript 语言通识 — 重学 JavaScript

三钻

JavaScript 前端进阶

SpringBoot-技术专题-启动原理

李博@Alex

Nacos-技术专题-配置中心实现

李博@Alex

EffectiveJava读书笔记-01-对象创建与销毁

wander

读书笔记 编程开发

深入分析CRM系统对现代企业的作用

Learun

字节跳动 Flink 单点恢复功能实践

Apache Flink

flink

互联网应用系统技术方案主要解决什么问题?

博古通今小虾米

2020年秋招阿里136道Java高级岗面试题(含答案及复习资源)

Geek_71bb95

Java 程序员 面试 算法 编程语言

Java程序员月薪多少K才能在北上广买得起房?

Geek_71bb95

Java 程序员 编程语言

MySQL-技术专题-问题分析

李博@Alex

Python时间序列分析简介(2)

计算机与AI

Python 时间序列

开源=免费?

Learun

从构建小系统到架构分布式大系统,Spring Boot2的精髓全在这里了

Geek_71bb95

Java 程序员 面试 Spring Boot 编程语言

MySQL-技术专题-主从复制原理

李博@Alex

节日快乐…吗?

小天同学

个人感悟 国庆中秋 假期 节日

spring-boot-route(十)多数据源切换

Java旅途

Java Spring Boot

lldb常用命令与调试技巧

iOSer

ios lldb常用命令 lldb调试技巧

光大银行刘淼:基于华为云GaussDB(DWS) 数据仓库创新实践

华为云开发者社区

数据仓库 数据 huawei

PyFlink + 区块链?揭秘行业领头企业 BTC.com 如何实现实时计算

Apache Flink

flink

如果朋友圈没有点赞功能,你还会发朋友圈吗

彭宏豪95

微信 产品 互联网 写作

~~寒露节记~~

wo是一棵草

关于代码审查的一点体会

KJ Meng

敏捷开发 研发管理 代码审查 Code Review

Web前后端:如何分离,如何解耦?

华为云开发者社区

后端 开发 开发前端

来不及解释了,快上车!力软快速开发平台,助力企业搭乘万物互联的顺风车

Learun

区块链数字钱包技术开发,数字资产钱包

135深圳3055源中瑞8032

架构师训练营1期第三周作业

木头发芽

国庆期间,我造了台计算机

yes的练级攻略

计算机 底层

MySQL-技术专题-查询速度性能

李博@Alex

技术实操丨SoundNet迁移学习之由声音分类到语音情感识别

华为云开发者社区

AI 数据 语音识别

极致体验 全球布局—构建安全且高速的企业级CDN研讨会

极致体验 全球布局—构建安全且高速的企业级CDN研讨会

优酷暗黑模式(八):分发场景落地(Android & iOS)-InfoQ