工作台上一台折叠设备停在半开角度,一侧架着拍摄用的支架,另一侧屏幕上排着一列还没打勾的测试状态表

一、门槛落在材料上,工程就会往材料靠拢

据公开报道,有厂商在官网发过公告:从公告设定的时点起,提交到应用商店的全新应用和版本更新都要附带一款新折叠机型在外屏与内屏两种形态下的运行截图作为审核材料,覆盖应用与游戏两大类,不设品类豁免。公告的具体生效细节、审核方如何核验截图与真实运行的一致性,我们不做推断,也不在这里讨论这条要求本身该不该有。我们只处理它带来的一个工程后果:当验收的门槛写成”提交哪几张图”,团队的工作量就会自动往”拍出这几张图”移动。

这不是谁的偷懒,而是流程的必然。验收标准是一种激励,它精确地度量了成本落在哪里。截图是静态的、一次性的、能归档的,因此它是好材料;真实运行是动态的、要花时间跑的,因此它是坏材料。要抵抗这个倾斜,只有一个办法:把”能提交截图”和”已经验证过适配”拆成两件有独立证据的事,前者从后者自动产出,而不是手工准备。

我们把这类现象叫拍照工程:为验收留下一张好看的照片,而照片背后那条路径没人走过。下面讲的都是围绕一件事——怎么让照片变成运行过程的副产品。

二、截图证明了什么,证明不了什么

一张外屏截图、一张内屏截图,能证明的东西比很多人以为的少。它能证明这个页面在这个尺寸下画出了内容、没有明显的溢出与空白色块、关键控件在画面上可见。这四条确实是适配的一部分,缺了它确实不该过。

它证明不了的,恰好是使用这个形态时会坏掉的那部分。输入过程:内屏上弹出输入法后视口被压缩,页面是否还能提交,截图里没有键盘。旋转:同一形态下两个方向的布局管线经常只跑通了一个。半折叠角度:设备立在桌面上呈帐篷状时的可用区域和悬停态交互,是这类机型特有的一档状态,两张整开与闭合的图都盖不到。分屏与多任务:面积被临时切走一半时的断点行为,和全屏截图不是同一个布局结果。跨形态切换时的状态续接:从外屏切到内屏,刚才填了一半的表单、看到一半的位置、播了一半的音视频去了哪里,静态图无法表达”切换”这个动作本身。还有性能与稳定性:截图不体现掉帧、不体现切换时的短暂闪退,而后者才是这类适配最容易出的事故。

于是判断标准应该是:一张图上的信息量,等于一个页面在一个形态下的一个瞬间。而一个折叠形态可用的应用,需要的是每个页面在每个形态下每个可交互瞬间都成立。这是几百上千个状态,不是一个乘二。

三、必测面拆成布局面与状态面,两张清单分开维护

第一类是布局面,它跟尺寸与密度有关,可以通过静态比对来判断。每一项都要在两个形态各自跑一遍:安全区与系统栏避让,内屏的圆角与屏下摄像区是外屏没有的;断点与栅格列数,折叠态与展开态的宽度差往往跨过了设计时没预留的断点;字重与行高,同一套字号在小屏可读、在大屏显松,或者反过来在窄条上换行成三行;可点区域尺寸,内屏上手指可达范围变大,但外屏上的最小热区要求一点没松;横向滚动与内容截断,长表格在大屏上不再需要横向滚动,这本身就是行为改变。

第二类是状态面,它跟时间有关,静态图基本帮不上忙。每一项都要以”操作序列”的形式来测:焦点在两个形态间切换后落在哪个控件上;输入光标位置与已输入内容是否续得上;列表滚动位置,展开后是按比例映射还是回到顶部;媒体播放进度与音频焦点;未提交表单的草稿内容;导航栈——内屏的单栈在展开后变成双栏主从结构时,返回行为怎么定义;下载或长任务在切换时是否被重发。

这两类清单要分开维护,因为它们的变化速度不同。布局面在项目做完响应式改造后基本稳定,状态面每个版本都会因为新页面而增长。把两者混在一张”适配检查表”里,结果通常是每次只勾布局那半张。

四、切换瞬间的三种策略,”保持”最难在哪

折叠与展开的瞬间,界面要选一种活法。重建:切换时销毁当前界面按新尺寸重画。它最省事、最不容易出视觉问题,也是审核方最容易看到两张漂亮图的策略,代价是状态全丢。用户视角的体感是”我一掰开手机,刚才填的东西没了”。保持:把当前状态原样迁移到新布局。用户感觉最好,也最难得多。降级:识别出某些页面迁移代价过高,主动切换到简化视图并告知用户。它需要额外交互设计,但比假装”保持”要诚实。

“保持”之所以难,不在动画,而在两套尺寸管线与实例生命周期不同步。布局测量与重排在切换那一刻是分两路推进的,而界面实例的存活期、状态对象的持有关系、异步回调的到达时间并不跟着布局走。于是典型故障不是画错,而是状态错位:旧尺寸下算出的偏移量被用在新布局上,或者状态对象在重建窗口里被回收,而迁移代码还拿着它的引用。这类问题在单形态设备上根本不存在,所以团队的既有回归经验在这里帮不上忙,必须新建。

洹拓给客户的取舍建议是按页面显式登记,而不是靠代码里的口头约定:哪些页面承诺保持,哪些页面走重建并在重建后恢复可恢复项(滚动位置与草稿),哪些页面直接降级。把它写进页面清单,比写进约定可靠得多,因为它同时也是给验收看的那份说明。

五、做成可回归的东西:分工、采集与三维矩阵

真机与仿真器的分工按”状态面归真机、布局面归仿真器”来切。仿真器和预览环境跑全量的布局比对,快、可并行、覆盖尺寸范围广;真机只承担三件事——半折叠角度的悬停行为、切换瞬间的状态迁移、以及输入与传感器相关的交互。这两者不是替代关系,用仿真器截图代替真机运行,等于把上面第四节的难点整体跳过。

截图的来源必须是自动采集,这是拍照工程与验收工程唯一实质的分界线。做法是把采集挂在真实运行上:回归任务在设备上按用例脚本走一遍页面与操作序列,在预定义的断言点自动出图,图与用例编号、构建版本、设备形态、执行时刻绑定,一同归档。提交审核用的图从这批产物里选,而不是另起一炉单独摆拍。这样做的副产品很实用:任何一张被质疑的截图,都能倒推出它是哪一次运行、哪一步操作、哪个构建版本产生的。

回归用例集按三个维度展开:形态、页面、关键状态。矩阵不能全填,全填跑不动,取舍办法是按”该页面是否含输入、含媒体、含长任务”决定要覆盖哪几档状态。下面是一个真实的填法示意,行是用例编号,列是必须留下的断言点。

页面 外屏输入态 外屏切换瞬间 内屏输入态 内屏半折叠 跨形态状态续接
登录与表单 必测 必测 必测 抽测 必测
列表与详情 必测 必测 必测 必测 必测
播放与音视频 抽测 必测 必测 必测 必测
图表与报表 必测 抽测 必测 抽测 抽测
设置与偏好 抽测 抽测 必测 免测 必测

游戏在这个矩阵上要额外加两栏,因为它遇到的是一组两难。渲染分辨率与帧率预算随形态改变:内屏面积与像素量都上去了,同一档画质设置下的 GPU 预算完全不同,外屏达标的帧率在展开后可能撑不住,而”展开后自动降画质”又会被用户感知为变模糊。输入方式也要切换:外屏适合单手拇指区,内屏的可点位置整体重排,虚拟摇杆与技能区的布局不是等比放大就能用的。这两项都要在矩阵里显式立项,否则上线后的问题会以”发热掉帧”的形式回到工单里。

六、上线前的抽样复核与灰度回看

上线前做一次抽样复核,抽的不是页面而是会话:随机挑若干条真实操作路径,从冷启动开始一路走完,中途做两次折叠展开,看整条路径上的状态是否自洽。这个动作没人愿意做,因为它无法自动化、也无法产出可以提交的图片,但它恰好是唯一能同时检验布局面与状态面的手段。我们的做法是把它做成发布流程里的一个签核项,每次发布固定抽样若干条,记录发现的问题数,长期看这个数的趋势。

灰度阶段的回看指标要挑能反映切换代价的那几个:异常退出率按形态分开统计,不能只看总体;跨形态切换后的用户放弃率,即切换动作之后短时间内结束会话的比例;切换后一定时长内的重复返回次数,它是”状态丢了用户正在往回找”的间接信号;画质与帧率档位变更后的投诉关键词,游戏类项目专用。这些指标不必精确,但要在切换功能上线前就有基线,否则灰度期看完数据依然只能靠猜。

核心交付物是两份。第一份是双形态回归用例矩阵,也就是第五节那张三维表加上每个用例的断言点清单,它决定测试跑什么。第二份是截图采集流水线与真实运行绑定的做法说明:采集点定义、产物命名规则、图与构建版本和形态状态的绑定字段、以及”提交审核用的图只能从流水线产物里取”这一条硬约束。第二份比第一份重要——矩阵可以照抄,但只有采集环节绑死了,截图才不会退化成拍照。至于”这个应用真的支持两种形态吗”,最后仍然要靠那张矩阵的覆盖范围来回答,而不是靠那两张图。