01 从一次多窗适配开始
OriginOS 6 Fold 希望为 X Fold 内屏提供一套新的多窗体验。窗口开始支持连续调节大小之后,同一个应用不再只是面对几个固定画布,而是需要在不断变化的空间里始终保持可用。
最直接的办法,是增加几种窗口状态,再让各个应用分别适配。但这样很快会遇到一个问题:下一种设备、下一种窗口形态出现时,我们是不是还要重新解决一次相同的问题?
窗口变化也不只是简单的变宽和变窄。导航可能从底部移到侧边,单列可能变成双列,次要信息可能需要收起,控件本身也可能改变形态。如果这些判断都交给各个应用独立完成,相似场景很容易形成不同规则,设计和开发也会反复处理同一类问题。
因此,这次项目没有停留在完成一次 Fold 多窗适配,而是进一步尝试建立一套公共规则,回答几个更基础的问题:什么应该保持稳定,什么可以随着空间变化,什么时候需要切换结构,以及有限的空间应该优先留给什么。
02 先把变化分成两个层级
为了让不同模块能够用同一种方式理解和讨论适配,我们先把界面变化拆成两个层级。
- 宏观层处理整体结构的变化。系统沿用紧凑、扩展和沉浸三种布局模式,通过断点决定导航位置、单列或分栏等整体结构。
- 微观层处理同一种结构里的连续变化。在两个断点之间,元素怎样伸缩、哪些信息先收起、多个区域怎样分配空间,都需要在这个层级继续判断。
无论具体采用哪一种方式,我们都希望变化尽量满足四个基本要求:结构稳定、内容清晰、交互连续、变化可预期。
微观层首先需要统一界面“可以怎么变”。我们把常见变化归纳成拉伸、缩放、缩进、延伸、挪移、分栏等基础方式。但知道怎么变还不够,当多个区域同时存在时,更重要的问题往往是:谁应该先获得空间,谁又应该先承担压缩。
03 当三列都能变化,空间应该先给谁?
「侧边导航栏 + 分栏」是弹性控件里讨论时间最长的一类场景。一个典型界面同时包含侧边导航、列表和详情三个区域,三列本身都可以伸缩,但“都能变化”并不意味着它们应该一起变化。
窗口变宽或变窄时,我们真正需要决定的是:新增的空间应该先给谁,空间不足时又由谁先承担压缩。
团队当时讨论过两种方式。第一种是尽量保持侧边导航和列表的默认宽度,或者保留用户主动调节后的宽度,让详情区域优先吸收新增空间,也优先承担压缩;另一种则是给三列设置不同权重,让它们随着窗口共同伸缩。
我更倾向第一种方案。
默认宽度通常代表系统对信息密度、可读性和操作效率的建议,而当用户主动拖动列表宽度时,这个尺寸也开始包含用户自己的使用偏好。窗口尺寸变化只是外部环境发生了变化,并不意味着用户同时改变了自己的偏好。
相比之下,详情区域通常承载当前任务的主要内容,本身也更适合消化连续的空间变化。因此,只要保证最低可用尺寸,让详情优先承担窗口伸缩,会比同时改变三列更加稳定。
用动态原型把讨论放进真实变化里
这轮讨论进行了一段时间后,我们发现,只看几张静态稿很难真正判断两种方式的差异。窗口变化是连续的,每个人脑中想象的过程又不完全一样,讨论很容易停留在各自的理解里。
于是我用 Gemini 做了两套可交互 Demo,把当时已经确定的尺寸参数和两种空间分配逻辑放进同一个可调窗口。大家可以直接拖动窗口,连续观察三列怎样变化,而不是只比较几个被截取出来的状态。
这个 Demo 并没有改变原本的设计方法,原型验证本来就是设计过程的一部分。真正发生变化的是制作成本和迭代速度:我可以更快把抽象规则变成一个能直接操作的体验,也能在讨论过程中修改参数、马上看到结果。
最终,两种方案的差异和实现边界都变得更清楚,这个 Demo 也成为后续规则确认和开发讨论的重要输入。
三列布局只是其中一个例子。项目中,我还继续定义了其他弹性控件在不同断点下的形态,以及区间内信息如何保持、压缩、重排或隐藏。它们面对的问题各不相同,但判断的基础是一致的:先保证当前任务和主要内容,再让次要信息承担空间变化。
04 有限的模板,怎样覆盖不同业务?
弹性控件处理的是单个界面元素怎样变化。再往上一层,还有另一类会反复出现的问题:一整组内容应该怎样一起变化。
团队先盘点了系统一、二、三级中的大量真实界面,从中归纳高频出现的布局场景。另一位同事先完成了第一个布局组件,为规范结构打样;我沿用这套结构继续负责「内容列表」,并比较不同场景下的内容量、首屏曝光目标和浏览方式。
最终,内容列表被归纳为两种变化逻辑。
- 拉伸型适合内容量有限、希望尽量在当前界面直接展示的场景。内容会随着空间伸缩,并在达到特定宽度后增加或减少列数。
- 延伸型更适合内容本身较多、原本就只能展示一部分的场景。单个项目保持相对稳定的尺寸,内容继续向一个方向延伸,并通过局部露出提示后面还有更多内容。
真正困难的地方并不是把两种模板画出来,而是决定模板应该规定到什么程度。规则太固定,很多实际业务无法使用;开放得太多,不同模块又会重新形成完全不同的结构,公共组件也失去了意义。
因此,我继续把既有界面拆成组件和子组件两个层级:跨应用反复出现、真正影响布局稳定性的关系由组件固定下来;具体业务内容和局部组合上的差异,则交给子组件和受控的自定义区域。
这些自定义仍然需要遵守统一的断点、变化优先级和多语言规则。最终,我完成了两类内容列表在三个断点下的布局关系、区间变化和多语言处理方式。
05 规则写完之后,怎么进入整个系统?
公共规则和组件完成之后,这个项目还有另外一部分工作:让不同模块真正知道怎样使用它们。
公共能力可以解决反复出现的问题,但不可能提前覆盖每一个业务细节,也不能替模块设计师判断自己的内容。因此,我们还需要让所有模块知道从哪里开始、需要输出什么,以及遇到通用规则无法处理的情况时该怎么继续推进。
公共团队一起讨论了配套方式,我主要负责内容组织、规范宣贯,并持续跟进交互侧的实际使用。具体包括三件事:在设计开始前,通过支持无级调节的 APK 提前检查不同窗口尺寸下的问题;在整体策划模板中增加「自适应布局」章节,统一必要的输出内容;适配过程中继续提供答疑和方案评审,处理无法直接套用公共规则的场景。
这些工作并不是替模块完成设计,而是把一个范围很大、起点并不清楚的任务,变成一套大家知道怎么开始、怎么检查、怎么说明,也知道遇到问题后怎么继续推进的过程。
06 从规则到真实产品
最终,全系统应用的核心界面完成了流动界面框架适配,规范、公共侧开发与模块开发均完成交付。相关能力于 2026 年 6 月 26 日随 vivo X Fold6 正式发布,作为多窗体验的公共基础能力进入产品。
这个项目最后留下的并不只是几套 Fold 界面。更重要的是,面对新的窗口尺寸或设备形态时,很多基础问题不再需要每个模块重新从头判断,而是已经有了一套可以共同遵循的规则和实现基础。
项目之后
这个项目最开始只是为了处理一个可以不断改变大小的窗口。做到后面,我对系统设计也有了更具体的理解:很多时候,难点不是把某一个页面设计好,而是从大量场景里找到反复出现的问题,再判断哪些应该成为公共规则,哪些仍然需要留给具体业务处理。
规则确定也不是结束。它还需要被验证、实现,并最终被不同团队真正使用。对我来说,这个项目也是工作视角的一次变化:从解决一个具体界面的问题,进一步走到一套系统能力如何被定义、验证并真正进入产品。