自从2.3.0版本来,手表客户端加了液态玻璃效果,实际上的效果我本人是相当满意的(也有用户反馈观感不错)
但是,相信眼尖的用户有注意到,开启玻璃后,手表会变得卡顿,这是为什么呢?
首先,一块组件想要有液态玻璃的效果,就要先拿到背后页面的画面,再做折射采样,最后显示出来。
但是,在安卓13以下,系统并没有给我们提供原生的取景通道。所以我们就必须每帧把整页内容重录成软件镜像再采样,这就导致卡片越多,布局越复杂的页面性能越差。
当然,在安卓13及以上,因为有官方的GPU通道(系统 AGSL),就不需要软件重录,所以性能开销非常低。
以下是各个安卓版本下玻璃的实现机制:
本质上都是采取组件后显示的内容,并对其进行折射计算。算法在各个安卓版本和各种渲染途径上已经尽可能统一,因此视觉效果基本上一致。
Q&A环节:
Q:那既然低版本安卓液态玻璃如此吃性能,是不是屏幕每次刷新都需要渲染?
A:当然不是,假设手表刷新率为60hz,如果按照Q的逻辑,不滚动软件页面时,液态玻璃以每秒60次进行采样计算,这对手表的电池,占用都十分不友好。并且,本客户端采用的是自研页面栈,会保留6到10层的旧页面,如果进入比较深的页面,那总刷新次数,连手机都会卡顿。
Q2:那怎么解决呢?
A2:液态玻璃只能在必要的时候进行刷新,所以需要详细控制液态玻璃何时刷新:
Q3:那有没有什么思路,可以从根本上解决这个问题呢?
A3:问得好,不妨换一种思路,某个组件的动画开始播放的时候,能不能同时通知玻璃并让其开始刷新呢?
经过研究后,发现Compose确实有这种机制,所以2.3.9版本会在根本上对类似问题进行修复。得益于日益统一的代码架构,我们对动画时长的控制,几乎已统一成一套口径。因此,只需在触发动画到动画结束的时间范围内,驱动玻璃更新即可。
Q4:我感觉这个软件功能已经很多了,怎么做到安装包体积还在5m以下的?
A4:客户端安装包的体积控制是个很大的难点。特别是在圆屏布局和方屏布局双线并行的情况下,这意味着每新加一个页面,就需要写两份代码。粗略计算可以认为我们的代码量是需要双倍于正常情况。
Q5:那怎么解决?
A5:尽量减小代码量。对于方圆两族,核心差异在布局,而底层的数据处理逻辑等都是一致的。因此,将这些相同的逻辑抽取为许多logic文件,只保留两边的布局代码即可达成目的。
另外,我们还设计了很多公用组件,比如“WatchCard”“RoundCard”(公用卡片组件)“WatchButtons”(按钮组件)“ScaledLazyColumn”(缩放滚动容器)“AppTextField”(全局输入框)等等等,在各个页面,只需要调用这个组件,就可以显示出相应的内容。这样既可以减少代码量,也可以保证各个页面的样式统一。
Q6:我感觉这个软件的UI很好看,但是说不出来为什么,这是什么情况?
A6:在开发之初,客户端对UI设计就十分注重。对于圆角、边距、颜色等,都有许多固定档位。
拿边距举例:项目内有定义SpacingXS,SpacingS,SpacingM,SpacingL等边距,圆角等也是如此。
后续在写新布局的时候,就不会额外造出新的边距,而是复用已经定好的数值,这样全局页面风格等都会比较统一,代码形态也比较优雅。对于卡片,我个人觉得视觉重心和同心圆是个很必要的东西。视觉看起来均衡就是最好的设计(个人观点,不代表真理)。至于同心圆,上图!
可见这些图片中,内层组件和外卡片的圆角十分协调,就像是同一个圆上的许多圆环,这样的设计相对来说,是比较协调的。那至于其他细节,就等待用户挖掘啦!
最后,希望你会喜欢本客户端!也希望你会喜欢本站!
但是,相信眼尖的用户有注意到,开启玻璃后,手表会变得卡顿,这是为什么呢?
首先,一块组件想要有液态玻璃的效果,就要先拿到背后页面的画面,再做折射采样,最后显示出来。
但是,在安卓13以下,系统并没有给我们提供原生的取景通道。所以我们就必须每帧把整页内容重录成软件镜像再采样,这就导致卡片越多,布局越复杂的页面性能越差。
当然,在安卓13及以上,因为有官方的GPU通道(系统 AGSL),就不需要软件重录,所以性能开销非常低。
以下是各个安卓版本下玻璃的实现机制:
| Android 13 及以上 | Android 8.0–12L | Android 6–7.1 | Android 5.0–5.1 |
| 官方 GPU 通道。也可选用软件逐像素折射 | 自写 OpenGL ES 2.0 折射,在不同设备上,流畅度可能有区别,也可选用软件逐像素折射 | 使用软件逐像素折射:在裁剪分辨率下算 sdRoundedRect + circleMap + 梯度位移 | 使用平台隐藏的 android.graphics.RenderNode 反射录制,像素与旧路径一致 |
Q&A环节:
Q:那既然低版本安卓液态玻璃如此吃性能,是不是屏幕每次刷新都需要渲染?
A:当然不是,假设手表刷新率为60hz,如果按照Q的逻辑,不滚动软件页面时,液态玻璃以每秒60次进行采样计算,这对手表的电池,占用都十分不友好。并且,本客户端采用的是自研页面栈,会保留6到10层的旧页面,如果进入比较深的页面,那总刷新次数,连手机都会卡顿。
Q2:那怎么解决呢?
A2:液态玻璃只能在必要的时候进行刷新,所以需要详细控制液态玻璃何时刷新:
- 对于页面栈,已经实现了非顶层页冻结玻璃刷新。
- 对于页面,不滚动的时候就停止刷新。
- (当然这也是很容易出bug的位置,之前版本上传进度不刷新,动画卡住,个人主页玻璃黑色的问题等,其实都是刷新机制不完善引入的bug)
Q3:那有没有什么思路,可以从根本上解决这个问题呢?
A3:问得好,不妨换一种思路,某个组件的动画开始播放的时候,能不能同时通知玻璃并让其开始刷新呢?
经过研究后,发现Compose确实有这种机制,所以2.3.9版本会在根本上对类似问题进行修复。得益于日益统一的代码架构,我们对动画时长的控制,几乎已统一成一套口径。因此,只需在触发动画到动画结束的时间范围内,驱动玻璃更新即可。
Q4:我感觉这个软件功能已经很多了,怎么做到安装包体积还在5m以下的?
A4:客户端安装包的体积控制是个很大的难点。特别是在圆屏布局和方屏布局双线并行的情况下,这意味着每新加一个页面,就需要写两份代码。粗略计算可以认为我们的代码量是需要双倍于正常情况。
Q5:那怎么解决?
A5:尽量减小代码量。对于方圆两族,核心差异在布局,而底层的数据处理逻辑等都是一致的。因此,将这些相同的逻辑抽取为许多logic文件,只保留两边的布局代码即可达成目的。
另外,我们还设计了很多公用组件,比如“WatchCard”“RoundCard”(公用卡片组件)“WatchButtons”(按钮组件)“ScaledLazyColumn”(缩放滚动容器)“AppTextField”(全局输入框)等等等,在各个页面,只需要调用这个组件,就可以显示出相应的内容。这样既可以减少代码量,也可以保证各个页面的样式统一。
Q6:我感觉这个软件的UI很好看,但是说不出来为什么,这是什么情况?
A6:在开发之初,客户端对UI设计就十分注重。对于圆角、边距、颜色等,都有许多固定档位。
拿边距举例:项目内有定义SpacingXS,SpacingS,SpacingM,SpacingL等边距,圆角等也是如此。
后续在写新布局的时候,就不会额外造出新的边距,而是复用已经定好的数值,这样全局页面风格等都会比较统一,代码形态也比较优雅。对于卡片,我个人觉得视觉重心和同心圆是个很必要的东西。视觉看起来均衡就是最好的设计(个人观点,不代表真理)。至于同心圆,上图!
可见这些图片中,内层组件和外卡片的圆角十分协调,就像是同一个圆上的许多圆环,这样的设计相对来说,是比较协调的。那至于其他细节,就等待用户挖掘啦!
最后,希望你会喜欢本客户端!也希望你会喜欢本站!
最后编辑: