发布在即!企业 AIGC 应用程度测评,3 步定制专属评估报告。抢首批测评权益>>> 了解详情
写点什么

优酷暗黑模式(十):消费场景落地(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:001524

评论

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

集成Health Kit时因证书问题出现错误码50063的解决方案

HMS Core

HMS Core

这一次,NineData新功能上线,真的是拼了

NineData

人工智能 sql 开发规范 数据复制服务 企业开发系统

春招升级打怪拿offer,10w+字总结的Java面试题(附答案)够你刷

做梦都在改BUG

Java java面试 Java八股文 Java面试题 Java面试八股文

Github点击破百万!这部《从零开始学架构》神书就此霸榜

Java你猿哥

Java 架构 ssm 面经 架构实战

狂刷《Java权威面试指南(阿里版)》,冲击“金三银四”有望了

做梦都在改BUG

Java java面试 Java八股文 Java面试题 Java面试八股文

天天预约 | 预约小程序分销功能,最全的操作指南来啦!

天天预约

小程序 SaaS 系统 预约工具 分销

使用 Metabase 连接 Databend Cloud 实现大屏展示

Databend

阿里是如何使用分布式架构的?阿里内部学习手册分享

Java你猿哥

分布式 ssm 分布式架构 分布式实战

贪心算法思想与练习

timerring

贪心算法

人工智能打造充满创造力的新世界,华为云开发者日无锡站成功举办

华为云开发者联盟

人工智能 华为云 元宇宙 华为云开发者联盟 企业号 3 月 PK 榜

流批一体在 AI 核心电商领域的探索与实践

Apache Flink

大数据 flink 实时计算

我有一篇Java Stream使用手册,学了就是你的了!

做梦都在改BUG

2023年金三银四牛客网一线大厂Java面试大全(1000道题目附解析)

采菊东篱下

Java 程序员 面试

视频编辑场景下的文字模版技术方案

百度Geek说

企业号 3 月 PK 榜 视频编辑 端渲染 富文本素材

机器学习算法(二): 基于鸢尾花数据集的朴素贝叶斯(Naive Bayes)预测分类

汀丶人工智能

数据挖掘 机器学习

熬了一个月肝完这份阿里P8的Java面试手册,我从20K变成了30K

Java你猿哥

Java 面经 校招 春招 八股文

卷起来了!阿里最新出品“微服务全阶笔记”,涵盖微服务全部操作

程序员小毕

Java 程序员 微服务 SpringCloud springcloudAlibaba

源码中常见的 where 1=1 是一种高级优化技巧?

Java你猿哥

Java 源码 ssm

微信小程序管理软件有哪些特点?

没有用户名丶

微信小程序

视频动态壁纸:Dynamic Wallpaper 激活版

真大的脸盆

Mac Mac 软件 动态壁纸 高清动态壁纸

机器学习算法(三):基于horse-colic数据的KNN近邻(k-nearest neighbors)预测分类

汀丶人工智能

数据挖掘 机器学习

太全了!马士兵内部共享—1658页《Java面试突击核心讲》

做梦都在改BUG

Java java面试 Java八股文 Java面试题 Java面试八股文

即时通讯技术文集(第10期):IM通信协议该选TCP还是UDP [共12篇]

JackJiang

MySQL kill会话不起作用?

GreatSQL

MySQL greatsql社区

牛客网Java面试题及答案整理(2023年春招最新版,持续更新)

架构师之道

编程 java面试

美团二面:细数 Redis 阻塞的9种情况

做梦都在改BUG

Java redis 面试

JVM级别的本地缓存框架Guava Cache:探寻实现细节与核心机制

Java你猿哥

Java JVM ssm Guava Cache

全新升级|ECS成熟度评估与洞察,助你精准定位运维风险

云布道师

ECS

TLS、SSL、CA 证书、公钥、私钥。。。今天捋一捋!

江南一点雨

gRPC TLS CA ssl

Qualcomm QCN9074 4x4 MIMO 802.11ax MX6974 F5 WIFI6 Module

MAXON

QCN9074

RabbitMQ 延迟消息实战

做梦都在改BUG

Java 消息队列 消息中间件 Rabbit MQ

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