写点什么

优酷暗黑模式(十):消费场景落地(iOS)

  • 2020-02-28
  • 本文字数:3836 字

    阅读完需:约 13 分钟

优酷暗黑模式(十):消费场景落地(iOS)

一、概述

iOS 13 中苹果引入了暗黑模式,提供了全新的配色方案,非常适合暗光环境下使用,对眼睛的伤害更小。为了配合优酷 App 全站暗黑模式的适配,我们需要在优酷主客消费场景将暗黑模式全面落地。


值得庆幸的是,在这之前优酷主客消费场景已经完成了统一架构迁移和性能优化,并在这个过程中完成了大部分插件的治理,遵循统一架构、组件标准化、DesignToken 设计,使得消费场景可以快速高效地支持暗黑模式。

二、业务介绍

优酷主客消费场景即优酷 App 的播放页。播放页作为视频内容消费的落地页,主要提供视频播放、视频内容介绍、互动、视频推荐、视频花絮、视频周边等内容推荐,业务场景及页面内容都比较复杂。根据场景分为:剧集、电影、综艺、少儿、体育、新知等;其内容有:组件、半屏、Tab 等。


组件:即视频相关内容承载控件,包括简介,选集,周边视频,花絮视频,推荐视频等,通过这些内容,让用户了解更多的视频相关的信息。


半屏:包括 Native、Weex、H5 的半屏,通过半屏用户可以看到更多的视频相关内容,也可以承载视频互动。因为组件展示的内容还是有限,通过半屏可以更好更全地展示。


Tab:通过 Tab 让用户在不同的内容之间切换。


播放页架构图:


1)页面、组件、坑位结构图:



2)业务效果图:


三、适配策略

1、页面适配

页面展现主要分为几种状态:加载态(Loading),展现态,异常态。主要工作可以分为加载态 LoadingView 适配,展现态背景色适配,异常态 ErrorView 适配。


按道理来说,背景色适配工作量会非常大,因为需要一层一层地去设置子 View 的背景色。但是由于优酷的视图中,大部分背景色是透明的,使得在进行暗黑模式适配的过程中非常便利,不用去一层一层的设置背景色,只需要适配容器 View 就可以。


[self.containerView setBackgroundColor:UIColor.ykn_primaryBackground]; //设置背景色,ykn_primaryBackground 为我们暗黑模式框架对外暴露的属性通过它可以取到对应的颜色[self.view setBackgroundColor:UIColor.ykn_primaryBackground]; //设置背景色
复制代码

2、组件适配、坑位适配

因为播放页都已经拆分为组件和坑位,所以完成页面部分的适配之后,主要就是对组件和坑位的适配。由于播放页组件完成度很高,所以在进行组件适配的时候也是比较顺利的。举个例子,播放页很多的组件都有 Header View,即左面会有文字,右面有一个箭头的 image。



当替换完 Header View 组件的图片,并进行完文字的暗黑模式适配后,所有这些 UI 布局全部完成了适配工作,从这里可以看出组件标准化的完成程度对后期业务的维护有着深远的影响。


_titleLabel.textColor = UIColor.ykn_primaryInfo;   //设置组件头部标题颜色_subtitleLabel.textColor = UIColor.ykn_secondaryInfo;  //设置组件头部副标题颜色_arrowImageView.image = UIImage.ykn_detail_comp_header_more;   //设置组件头部箭头图片
复制代码

3、半屏适配

半屏页面主要是分为 Native 半屏页面、H5 半屏页面、Weex 半屏页面。


由于所有的半屏页面都是由播放页半屏容器管理器来管理,所以只需要在里面统一适配即可;需要注意的是我们适配的只是 H5、Weex 的容器,容器里面的具体页面的适配详见: 暗黑模式的技术支撑(Weex&H5)。


举例来说,H5 半屏容器页面适配:


webViewController.view.backgroundColor = UIColor.ykn_primaryBackground;  //设置容器背景色webViewController.topBar.backgroundColor = UIColor.ykn_primaryBackground; //设置顶部导航背景色webViewController.titleLabel.textColor = UIColor.ykn_primaryInfo;  //设置顶部导航字体颜色[webViewController.closeBtn setImage:UIImage.ykn_detail_box_close forState:UIControlStateNormal];//设置顶部导航关闭按钮图片
复制代码

4、中间件处理,与沉浸式隔离

在适配暗黑模式之前,优酷播放页已经完成了沉浸式模式的开发。沉浸式使得用户可以快速地融入到内容本身中去,减少不必要的信息造成的视觉干扰,使用更有层次感的内容来引导用户聚焦,自然地实现播放器视觉 C 位呈现,其呈现效果与暗黑模式也有较大不同。


所以,在适配的过程中需要做一层颜色及资源管理层(架构图中的颜色资源管理层),来区分沉浸式氛围及暗黑模式。通过不同的开关控制背景处理及加载不同的资源、颜色。后期沉浸式模式将会接入优酷 App 的全局统一氛围配置,做到自动下发氛围相关样式,减少适配工作。



在进行与沉浸式隔离开发的时候我们遇到一个难点,在没有进行暗黑模式适配时候,沉浸式是通过函数


-(NSString *)immersionImageName:(NSString *)imgName


进行适配,该函数实现逻辑如下:


-(NSString *)immersionImageName:(NSString *)imgName{   if (self.isImmersionMode) {       NSString *name = [self.imgNameDic valueForKey:imgName] ? : imgName;       return name;   } else {       return imgName;   }}
复制代码


该函数首先会先判断是否为沉浸式模式,如果为沉浸式返回对应沉浸式的图片名称; 当找不到对应图片时,使用一个兜底图片。如果沉浸式没有生效则直接返回正常图片名称。


当适配暗黑模式时候遇到了难点,优酷设计标准化 SDK 是通过属性调用返回 UIImage 对象,所以需要改造该函数。


先贴上改造后结果:


-(UIImage *)immersionImage:(NSString *)imgName{   if (self.isImmersionMode) {       if ([self.imgNameDic stringForKey:imgName]) {           return [UIImage imageNamed:[self.imgNameDic stringForKey:imgName]];       }   }   SEL sel = NSSelectorFromString(imgName);   if ([UIImage respondsToSelector:sel]) {       return [UIImage performSelector:sel];   } else {       return nil;   }}
复制代码


首先将函数返回结果改为 UIImage 对象。这么改造有两点好处:


第一: 在业务方调用时,可以直接使用该函数返回的结果,不需要再调用函数


(nullable UIImage *)imageNamed:(NSString *)name


便于业务方使用。


第二: 如果当前为暗黑模式,可以直接返回该属性值,不需要进行转换等操作,提高运行效率、降低出错概率。


最后: 因为传进来的是图片名称,并且属性名称是与图片名称一致的,所以可以通过其属性 get 方法拿到对应图片。


总结一下该函数的逻辑:如果为沉浸式模式,返回对应的沉浸式 UIImage 对象 ,因为沉浸式业务优先级大于暗黑模式。如果不是沉浸式,通过 NSSelectorFromString 生成该属性 get 方法对应的 selector,判断是否存在该方法。如果存在该方法说明存在对应图片,调用该属性 get 方法并返回对应 UIImage 对象。

5、网络图片的适配

暗黑 SDK 是直接支持本地图片适配的,但是网络图片适配需要业务方来做。在播放页,有些图片是支持后台配置的。即当后台配置了图片下发,优先展示后台配置的图片,如果后台没有配置图片则展示本地图片。


例如下图中的热评、收藏、缓存、分享对应图片都是支持后台配置的。



那么问题来了,这种情况下如何进行暗黑模式的适配?


解决方案为提前准备好从网络下载的图片,对应的图片有两套即正常模式和暗黑模式。使用时候判断对应模式来使用对应图片。


示例代码如下:


UIImage *imageFromWeb1 ;//从网络下载成功的UIImageUIImage *imageFromWeb2 ;//从网络下载成功的UIImageUIImage *image = [UIImage ykn_imageWithThemeProvider:^UIImage * _Nonnull(__kindof YKNThemeManager * _Nonnull manager, NSString * _Nullable identifier, NSObject<YKNThemeProtocol> * _Nullable theme) {             //回调中不要做耗时操作,如是网络图,提前准备好图片             if ([identifier isEqualToString:YKNThemeIdentifierDark]) {                 return imageFromWeb1 ;  //dark模式下的图             }             return imageFromWeb2; //light模式下的图         }];
复制代码

四、适配效果


五、调试小技巧

在进行暗黑模式适配时候遇到这样一个问题,即每次改过 UI 我们都需要重新运行整个 App 才会生效。毫无疑问,这是十分浪费时间的,有没有什么方案可以做到不重新运行 App 即可生效的呢?答案是有的。


在模拟器上我们可以通过 InjectionIII 来进行热更新,具体方案不再赘述,网络上有很多介绍文档。这里只介绍真机实现方案。


实现方案:首先添加一个断点,接下来编辑断点并添加一个 Debugger Command 并输入表达式,最后选择 Automatically continue after evaluating actions。为什么要勾选这个呢?如果勾选上运行到该断点的时候不会停住,会自动执行表达式,并自动执行下一行代码。


六、项目总结

业务架构层面核心功能组件化的好处是巨大的,这使得代码按照功能模块高度聚合,只需要针对当前功能组件进行修改即可全局生效;UI 层级的扁平化及层级管理也是十分重要的。


通过暗黑模式的适配,大大的提升了优酷播放页的使用体验。这也是我们对 iOS 13 新特性的一个探索,并且在较短时间内拿出来一个成熟的暗黑模式适配方案,在优酷 iOS 端进行了尝试和使用,最终呈现的效果也是非常好的,通过这次的改造和实践也为我们以后对其它新技术的探索打了坚实的基础。


作者简介


子荀、金籽,阿里文娱无线高级开发工程师。


相关阅读


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


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


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


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


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


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


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


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


优酷暗黑模式(九):消费场景落地(Android)


2020-02-28 15:002076

评论

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

教你用Java字节码做点有趣的事

比伯

Java 编程 架构 程序人生 计算机

内存数据库解析与主流产品对比(三)

星环科技

数据库 大数据

阿里四年技术 TL 的得失总结:如何做好技术 Team Leader

阿里巴巴云原生

云计算 项目管理 程序员 微服务 云原生

一个 3 年 Java 程序员 5 家大厂的面试总结(已拿Offer)

Java架构之路

Java 程序员 架构 面试 编程语言

KubeVela:标准化的云原生平台构建引擎

阿里巴巴云原生

容器 云原生 k8s API OAM

新思科技发布《美国不良软件质量成本:2020年报告》

InfoQ_434670063458

软件质量 新思科技

产品训练营--第二期作业

曦语

产品训练营

“区块链新闻编辑部”: 从“云媒体”到“链媒体”的现实跨越

CECBC

区块链技术

区区一个SpringBoot问题就干趴下了?我却凭着这套“神级PDF文档”吊打面试官

Java 编程 面试 微服务

Dubbo 3.0 前瞻之对接 Kubernetes 原生服务

阿里巴巴云原生

容器 运维 云原生 k8s dubbo

三张图解释静态NAT、动态NAT、PAT

数据库恢复子系统的常见技术和方案对比(一)

星环科技

数据库 大数据

Elasticsearch 基于脚本进行 partial update

escray

elastic 七日更 28天写作 死磕Elasticsearch 60天通过Elastic认证考试

智能汽车为什么新势力有胜算(28天写作 Day20/28)

mtfelix

28天写作 新能源汽车 智能汽车 造车新势力

kotlin高阶函数let、with、apply、run、also使用场景

陈吉米

kotlin

开发质量提升系列:问题登记列表(下)

罗小龙

生产事故 28天写作 解决思路

nodejs的调试debug

程序那些事

debug 调试 nodejs 程序那些事 程序调试

【推荐收藏!】Gradle 与 Android 构建入门

百度Geek说

研发工具 andiod

Libra演进与数字货币国际化

CECBC

区块链

程序员入职新公司,只需8步,直接凸显出个人价值

Java架构师迁哥

抽奖助手利益相关方

千竹

《程序员修炼之道》- 务实的哲学(3)

石云升

读书笔记 程序员 28天写作 批判性思维 完成好过完美

数据库恢复子系统的常见技术和方案对比(二)

星环科技

数据库 大数据

30天消化MyBatis源码解析笔记,吊打面试官,offer接到手软

Java架构之路

Java 程序员 架构 面试 编程语言

5年Java经验不会源码被拒,苦学这些Spring源码笔记后,面试不再慌

Java架构之路

Java 程序员 架构 面试 编程语言

译文《最常见的10种Java异常问题》

潘大壮

Java 异常 java异常处理 Exception

Flink 学习路线总结

大数据学习指南

大数据 flink

10 个 JavaScript 简洁代码小技巧(文末彩蛋)

零和幺

JavaScript 大前端 CleanCode

拍乐云 Flutter SDK 全新发布,跨平台音视频开发更easy

拍乐云Pano

flutter 音视频 WebRTC RTC

Flink可靠性的基石-checkpoint机制详细解析

五分钟学大数据

大数据 flink

这是阿里技术专家对 SRE 和稳定性保障的理解

阿里巴巴云原生

项目管理 运维 云原生 安全 监控

优酷暗黑模式(十):消费场景落地(iOS)_移动_阿里巴巴文娱技术_InfoQ精选文章