写点什么

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

  • 2020-02-27
  • 本文字数:4502 字

    阅读完需:约 15 分钟

优酷暗黑模式(八):分发场景落地(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-02-27 15:001593

评论

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

直播程序源码OAuth协议:开放授权的重要性

山东布谷科技

软件开发 Oauth 源码搭建 直播程序源码 开放授权

从数据孤岛到企业 xP&A 的演化

智达方通

数据孤岛 全面预算管理 扩展规划和分析

Presto 设计与实现(十一):抽象语法树 AST

冰心的小屋

AST 抽象语法树 presto 设计与实现

全球前十的LED大屏幕租赁公司

Dylan

娱乐 科技 LED显示屏 led显示屏厂家 虚拟演唱会

小灯塔系列-中小企业数字化转型系列研究——SCRM测评报告

向量智库

纯CSS杂志封面折叠效果

南城FE

CSS 前端 动画 交互

DORA指标:公司业务成果的“占卜师”

SEAL安全

DevOps 运维‘ DORA 企业号 8 月 PK 榜

Mac电脑强大的图像编辑 Pixelmator Pro 中文直装

胖墩儿不胖y

图像编辑 Mac软件 图像处理工具

理解 Databend Cluster key 原理及使用

Databend

【深入MaxCompute】人力家:用MaxCompute 事务表2.0主键模型去重数据持续降本增效

阿里云大数据AI技术

MaxCompute

软件测试案例 | “某气候中心数据加工处理系统”软件项目验收测试

TiAmo

软件测试 测试

直播预告 | 博睿学院第四季-博睿数据资深运维团队现身说法!

博睿数据

直播 博睿数据 博睿学院

阿里云PolarDB分布式版,降价40%!

阿里云瑶池数据库

数据库 阿里云 polarDB

Java NIO 图解 Netty 服务端启动的过程 | 京东云技术团队

京东科技开发者

Java Netty 组件 企业号 8 月 PK 榜

R语言之 ggplot 2 和其他图形

timerring

R语言

macos虚拟定位软件推荐 AnyGo激活中文版

mac大玩家j

Mac软件 虚拟定位软件 好用的gps

英特尔数据中心突破创新,以全新架构点燃发展新引擎

E科讯

深度解析 PostgreSQL Protocol v3.0(一)

KaiwuDB

postgresql protocol KaiwuDB

新版Media Encoder 2023 mac下载 (me2023媒体编码器) v23.6激活版

mac

苹果mac Windows软件下载 Media Encoder 2023 视频编码软件 ME2023

企业诊断屋:在线小说企业如何用A/B测试赋能业务

字节跳动数据平台

大数据 ab测试 对比实验 企业号 8 月 PK 榜 数字化增长

MySQL redo log恢复原理 | StoneDB技术分享会 #5

StoneDB

MySQL 数据库 HTAP StoneDB

OpenSSL 3.0.0 设计(四)|代码维护、FIPS 测试

铜锁开源密码库

算法 测试 代码 密码学 openssl

zone.js由入门到放弃之二——zone.js API大练兵

OpenTiny社区

前端 zone.js

火山引擎 DataLeap 助你拥有 Notebook 交互式的开发体验

字节跳动数据平台

大数据 数据中台 数据治理 数据安全 企业号 8 月 PK 榜

MySQL Shell 8.0.32 for GreatSQL编译安装

GreatSQL

greatsql

OpenHarmony Meetup 2023 广州站圆满举办,城市巡回全面启航

OpenHarmony开发者

OpenHarmony

如何有效的给出反馈

ShineScrum

反馈 管理者 敏捷教练 如何反馈 coach

JVM锁优化:Java原生锁的背后!

java易二三

Java 程序员 接口 计算机

Vue3使用小技巧

青柚1943

OpenHarmony Meetup 2023广州站圆满举办,城市巡回全面启航

科技热闻

优酷暗黑模式(八):分发场景落地(Android & iOS)_移动_阿里巴巴文娱技术_InfoQ精选文章