写点什么

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

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

    阅读完需:约 11 分钟

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

优酷播放页的暗黑模式是在设计标准化的基础上,参考了 DesignToken 来实现设计的。之前播放页已经接入了组件标准化,为暗黑模式的适配提供了很大的便利。

一、播放页业务介绍

播放页作为用户视频消费场景的落地页,主要提供包括视频播放、内容介绍、互动、推荐、花絮、周边、推荐等。业务类别及页面元素都比较复杂,页面类别有:剧集、电影、综艺、少儿、体育、新知等;其元素主要有:组件、半屏、tab 等。


常见的几种页面类别及元素如下图所示。


二、播放页场景特殊性

相对于其它场景,播放场景有其特殊性。


首先,用户在观看视频的时候切换暗黑模式不能打断用户的操作(如定时切换),需要实现无缝切换以达到良好的播放体验,所以在切换模式的选择上和其它场景会有区别。


其次,播放页组件有 30 多个,同时还会有半屏(包括 native 及 H5),弹框,及少儿、评分、评论等其他业务团队页面的承接,UI 适配涉及改动点比较广。


最后,播放页原先已经具备沉浸式观影模式,在某些剧集上会生效,它也属于氛围的一种,需要做好隔离,避免与暗黑模式相互影响。

三、页面适配架构


播放页架构的最底层是优酷的统一渲染架构以及标准化组件。如前文所述,因为播放页有沉浸式观影模式,我们做了一层资源管理层,用于隔离沉浸式模式和暗黑模式,同时可以更好的统一管理播放页的资源,便于维护。最上层则为要适配的页面相关组件、半屏等。

四、页面适配方案

1、资源适配

资源适配主要有颜色适配和资源适配,两者都是采用标准化的方式来适配,适配方式可以参考《暗黑模式的技术支撑(Android)》。

2、刷新模式对比

2.1 Android 系统的两种刷新模式

Android 10 系统对于暗黑模式与正常模式的刷新采用两种刷新方式:


(1) recreate 方式:该方式下正常模式与暗黑模式切换时,会对整个 Activity 进行 recreate,绘制时根据模式,获取不同的颜色进行绘制,


(2) uimode 方式:即业务根据需要自行刷新模式,正常和暗黑模式切换时并不会 recreate 整个 Activity,需要业务自己去刷新要适配的页面和组件。这种模式需要在 AndroidManifest 的 configChanges 配置 uimode,防止进入 recreate 模式。

2.2 两种模式对比

recreate 方式:


  • 优点:适配简单,在适配时直接修改颜色为 DesignToken 动态色,资源放置在 drawable-night 下即可。当系统切换模式,recreate 整个 Activity 的时候自动获取颜色绘制。

  • 缺点:模式切换之后对于用户的体验不好,每次切换以后都会重新加载,用户之前的观看及操作会丢失,需要重新加载。


uimode 方式:


  • 优点:用户体验比较好,模式切换的时候可以无感知切换,不影响用户观看及之前的操作;

  • 缺点:适配刷新比较复杂,不会 recreate Activity 要主动去刷新,需要考虑弹框,半屏,及前后台切换影响。颜色适配及资源适配都需要手动获取设置。


对于两种刷新模式的选择,需要根据业务场景来选择适合哪种模式。对于优酷的分发页面,页面重建对于用户操作影响并不大,可以采用 recreate 模式,适配起来不用考虑主动触发刷新。

3、播放页具体刷新方案

从用户体验的角度出发,用户在观看视频的时候,并不想在任何时候被打断,最终采用 uimode 的方式来刷新整个页面,做到无感知刷新,防止 recreate 页面之后播放重新开始。这种情况下就需要页面主动去触发刷新。


播放页有 30 个多个组件,加上半屏、弹窗如果每个单独去刷新适配工作量太大,且像选集有很多分季 tab 及分集,单独去做刷新显然不太可能,所以需要比较通用的方式去刷新,做到一次调用整体刷新。


最终采用的方案是,将刷新分为三类:最底层整体页面与 tab、组件、半屏及弹窗,具体适配方案如下:


刷新适配时,通知刷新部分及资源选取(上面提到的资源适配)采用系统提供的方式,后面刷新过程中颜色处理还是按照组件标准化的统一规则(上面提到的颜色适配)来进行刷新适配。

3.1 触发刷新(系统的刷新方案)

采用系统提供的 uimode 模式,在 manifest 配置 uimode 模式防止 recreate activity


<activity    android:name="com.youku.ui.activity.DetailActivity"    android:configChanges="uiMode"Copy    监听onConfigurationChanged()来判断是否暗黑模式切换:@Overridepublic void onConfigurationChanged(Configuration newConfig) {             //普通与暗黑模式切换       int  currentNightMode = newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK;       if (mCurrentUIMode != currentNightMode) {        //通知刷新        .......    }}
复制代码


具体流程:


3.2 tab 与背景刷新

tab 和背景整体可以看作是一个页面承载底层,统一刷新来设置整个 tab 背景及页面最底层背景。刷新过程中注意 tab 的锚定,比如当前在第二个 tab,刷新之后也要锚定到第二个 tab。

3.3 组件刷新

每个组件可以看作是 RecyclerView 的一个子 View,所以刷新采用 Adapter 的 notifyDataSetChanged 方式。获取到整个加载组件的列表即 componentList,然后对每个 Component 的 Adapter 通过 notifyDataSetChanged 去调用整个组件的刷新,这个时候页面数据已经在本地存在,相当于只是刷新 View 样式。


这个过程中,遇到过一个问题就是播放页数据刷新的时候做了多次刷新的保护(下图中 check 组件是否可以刷新部分),所以如果不是数据的变化,则不会去执行刷新,要解决这个问题需要设置一个新的刷新状态,由于组件过多,只能采用统一处理的方式,在组件数据的统一父类中设置状态改变的方法;当判断出组件已加载,且 UI 模式已切换后,则设置组件可以刷新,在组件刷新时可以很方便拿到这个状态,判断该状态去刷新。


简单刷新流程概括如下:




后台切换刷新,不会影响观看

3.4 半屏及弹窗刷新

半屏及弹窗的刷新比较复杂,播放页整个半屏采用 View 打开的方式,且半屏对应也有很多种样式。比如多种展示 View,多种不同背景,外部页面(如评论部分,承接在播放页,背景需要播放页控制)透明背景等;同时也要考虑用户当前打开了半屏,然后退到后台再切换模式的情况。


在半屏适配采用的方案是:每次半屏的打开需要记录下来,刷新时判断容器当前是否正在打开,半屏的背景用同一个 tag 标记,当接收到刷新通知之后,判断当前打开的半屏,根据 tag 去刷新背景,这样就不用再每个半屏去处理,直接通过 tag 统一刷新。对于特殊半屏的刷新,实现调用刷新方法做特殊 Viewiew 的刷新处理,调用该方法进行各自 View 的刷新,具体流程如下:




半屏刷新,不会关闭半屏,直接切换

3.5 与沉浸式模式隔离

在适配暗黑模式的过程中,沉浸式模式与其会互相影响,需要做到相互隔离。下面是沉浸式的一个样式,该页面可以给用户更好的观影体验,背景采用高斯模糊图的方式,可以开关控制。


从页面可以看出,其效果也是对于不同样式的处理,但是沉浸式是运营控制开关投放,背景是一层高斯模糊,对于背景,字体,颜色的处理还是不同,所以在适配的过程中需要做一层颜色及资源管理层(架构图中的颜色资源管理层),来区分沉浸式氛围及暗黑的处理。通过不同的开关控制背景处理及加载不同的资源、颜色。后期沉浸式将会接入全局统一氛围配置,做到自动下发氛围相关样式,减少适配工作。


五、总结

1、根据自身的业务场景选择适合业务的刷新方式,比如播放页不能打断用户操作及观看,采用 uimode 方式;


2、模块比较多的情况下,尽量考虑相互关联的模块一起去处理刷新,提高适配效率;


3、同一类 View 比如半屏背景,或者 RecyclerView 采用统一的管理方式,做到一次调用,全部刷新;


4、有其他 UI 样式相关的处理比如换肤,氛围,要考虑相互之间的影响;


5、对于使用 uimode 模式,要考虑用户退出后台模式修改的情况,以及用户设定了具体时间进入暗黑模式的情况。当重新回到 App,做到无缝刷新;尤其在打开弹窗,半屏,tab 锚定的时候,具体效果可看下面适配效果。

六、适配效果


作者简介


吉欧,阿里文娱无线高级开发工程师。


相关阅读


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


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


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


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


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


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


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


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


2020-02-28 10:002205

评论

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

藏在Java数组的背后,你可能忽略的知识点

Java架构师迁哥

架构师课作业 - 第十三周

Tulane

记一种spring框架的想当然但错误的用法

小明同学

源码分析 最佳实践 Spring Framework bug

LeetCode题解:232. 用栈实现队列,使用两个栈 入队 - O(1),出队 - 摊还复杂度 O(1),JavaScript,详细注释

Lee Chen

大前端 LeetCode

区块链技术发展的十大趋势

CECBC

区块链 金融 安全问题

业务架构学习内容有哪些?

周金根

BIZBOK 业务架构

朱嘉明:全球科技革命正在逼近“奇点”,区块链影响未来人类社会的走向

CECBC

人工智能 科技 科技革命

宅家三个月玩转算法,再战字节跳动,字节跳动面试官朝我比了个“ok”

编程 字节跳动 面试 算法

基于Goc的Golang代码VSCode实时染色方案

大卡尔

测试覆盖率 精准测试 Go 语言

区块链赋能市场监管 浙江上线“黑科技”清除取证固证难题

CECBC

区块链 市场监管 取证难题

.NET委托,事件和Lambda表达式

AI代笔

LeetCode题解:232. 用栈实现队列,使用两个栈 入队 - O(n), 出队 - O(1),JavaScript,详细注释

Lee Chen

大前端

从新浪数字化转型,窥见互联网的“懂行”新十年

脑极体

TOGAF认证课由2天变化为5天的思考

周金根

企业架构 TOGAF

不要以为Bug写的好就是好程序员,其实这只占不到15%

小Q

Java 学习 程序员 架构 面试

【高并发】Redis如何助力高并发秒杀系统,看完这篇我彻底懂了!!

冰河

多线程 高并发 秒杀 电商超卖 签约计划第二季

阿里培训官给新入职程序员的25条建议

Java架构师迁哥

Dubbo-go应用维度注册模型

apache/dubbo-go

dubbo dubbo-go dubbogo

不草率,你只管下载资料,剩下的交给「哇哦」

小Q

Java 学习 架构 面试 分布式

JavaScript引擎的事件循环机制是怎样工作的?

Walker

Java 大前端 运行时栈帧 事件循环

oeasy教您玩转linux 010211 牛说 cowsay

o

澳门金沙玩赢了钱提现不了异常注单未更新有什么办法处理?

丛林里的余光

异常检测 澳门金沙 提现不了

面试必问亿级流量优化策略之JVM调优,文档视频面试,还不收藏

小Q

Java 程序员 架构 JVM jvm调优

一文解开java中字符串编码的小秘密

程序那些事

java安全编码 java编码指南 UTF编码

从外卖员到拼多多30K+程序员,我付出了三年的青春

小Q

Java 学习 程序员 架构 面试

甲方日常 13

句子

工作 随笔杂谈 日常

央行数研所推出贸易金融区块链平台

CECBC

区块链 金融

一点 Go Web 编程实践经验

Garfield

Go web Go 语言

Java四种引用类型:强引用、软引用、弱引用、虚引用

简爱W

架构师训练营第十四周

Melo

[翻译]Scalable Go Scheduler Design Doc[Go可扩展调度设计文档]

卓丁

golang scheduler Go scheduler Go 语言

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