【AICon】AI 大模型超全落地场景&最佳实践 了解详情
写点什么

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

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

    阅读完需:约 13 分钟

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

AI 大模型超全落地场景&金融应用实践,8 月 16 - 19 日 FCon x AICon 大会联诀来袭、干货翻倍!

一、概述

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:001576

评论

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

舔狗至高境界,学会这个技巧让你从舔狗升华到海王【Python趣味爬虫】

Geek_ac6fb9

后端

阿里云数据库PolarDB开源人才培养计划发布!万元好礼等你来拿!

阿里云数据库开源

数据库 阿里云 开源 认证 polarDB

文档管理系统对于企业来说有哪些作用?

Baklib

借问变量何处存,牧童笑称用指针,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang类型指针(Pointer)的使用EP05

刘悦的技术博客

入门 教程 Go web 教程分享 入门介绍

开源一夏 | jQuery对于链和捕获的实战研究

恒山其若陋兮

开源 8月月更

Go-Excelize API源码阅读(四)——Save()

Regan Yue

Go 开源 源码刨析 8月日更 8月月更

Spring Cloud Stream 消息发送

急需上岸的小谢

8月月更

培训预告 | 企业应用现代化实用教程——DevOps方法论及最佳实践篇 8月11日上线

York

DevOps 云原生 团队建设 降本增效 应用现代化

直播 | 服务餐饮商户年交易额超 7000 亿,哗啦啦如何用 StarRocks 搞定实时报表

StarRocks

数据库

抖音开启“818发现好物节”:电商平台造节活动何时休

石头IT视角

深度解读 | 关于SBOM最基础元素,你需要知道的(Part I)

安势信息

开源 漏洞 SCA SBOM 最基础元素

openEuler 资源利用率提升之道02:典型应用下的效果

openEuler

开源 数据 cpu 操作系统 openEuler

Unity Metaverse(四)、接入环信IM SDK 实现用户登录注册

CoderZ

Unity 登录验证 环信im 8月月更

开源一夏 | RuntimeException 子类

六月的雨在InfoQ

开源 8月月更

Netty入门 -- 什么是Netty?

Bug终结者

Netty 8月月更

MySQL权限管理

武师叔

8月月更

LeaRun模型驱动开发框架 重塑企业生产力

力软低代码开发平台

什么是Shell?从小白到入门你只差一个它

Albert Edison

Linux centos 运维 shell脚本编程 8月月更

【高并发】别闹了,要实现亿级流量下的分布式限流,这些算法你必须掌握!!

冰河

并发编程 多线程 高并发 协程 异步编程

分门别类输入输出,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang基本数据类型和输入输出EP03

刘悦的技术博客

golang 编程 教程 教程分享 golang 面试

头脑风暴:打家劫舍2

HelloWorld杰少

算法 LeetCode 动态规划 8月月更

微服务架构的核心关键点

阿泽🧸

微服务架构 8月月更

企业进行知识共享的好处有哪些?

Geek_da0866

兼容并蓄广纳百川,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang复合容器类型的声明和使用EP04

刘悦的技术博客

golang go doc 教程 教程分享 golang 面试

SRv6故障管理

穿过生命散发芬芳

8月月更 SRv6

如何让您的wiki内容更高级?

Geek_da0866

开源一夏 | 基于 Serverless一键体验FastAPI

六月的雨在InfoQ

阿里云 开源 Serverless FC 8月月更

Linux下Docker安装部署以及云原生的理解

Geek_acae888666

云原生 Docker 镜像

经验分享|低成本快节奏搭建企业知识管理系统的方法

Baklib

超人飞来!Flutter 实现满屏的力量感动画!

岛上码农

flutter ios 移动端开发 安卓开发 8月月更

低代码实现探索(四十七)低的不止前端,还有后端

零道云-混合式低代码平台

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