折叠态、半展开、全展开都要判断吗?HarmonyOS 7 折叠屏适配用窗口宽度更稳
折叠态、半展开、全展开都要判断吗?HarmonyOS 7 折叠屏适配用窗口宽度更稳
折叠屏适配很容易写成一串设备和姿态判断:某型号折叠时一列、半展开两列、展开三列。代码刚能跑,新设备或自由窗口一出现,判断就开始互相打架。真正决定内容能否排下的通常是当前窗口宽度,而不是设备叫什么、铰链处于哪个角度。

先把问题变成可验证的证据
响应式布局负责在不同窗口范围选择结构,自适应布局负责同一结构内伸缩。折叠姿态可以作为交互增强条件,但不宜成为内容布局的唯一依据。窗口变化时还要保证筛选、滚动位置和编辑状态不被重建丢失。
- 同一台折叠屏在分屏和自由窗口下可能拥有不同有效宽度。
- 姿态切换与窗口尺寸变化不是严格一一对应。
- 布局模式变化不应该顺便重置业务状态。
案例一:设备已经展开,分屏后仍强制三列导致内容被挤压
旧实现根据“展开态”固定三列,却没有读取当前窗口。改为按有效宽度计算模式后,分屏会自然回到单列或双列。
type Layout = { mode: 'single' | 'dual' | 'triple'; columns: number; sidePanel: boolean }
function resolveLayout(widthVp: number): Layout {
if (widthVp < 600) return { mode: 'single', columns: 1, sidePanel: false }
if (widthVp < 840) return { mode: 'dual', columns: 2, sidePanel: false }
return { mode: 'triple', columns: 3, sidePanel: true }
}
console.assert(resolveLayout(520).mode === 'single')
console.assert(resolveLayout(760).mode === 'dual')
console.assert(resolveLayout(980).sidePanel)
布局只依赖当前可用空间,折叠、展开、横竖屏和分屏都能落到同一套规则。
案例二:从半展开切到全展开,搜索词和滚动位置全没了
把页面状态放在每个布局分支内部,会在模式切换时重新创建。应先保存业务状态,再让布局只消费同一份状态。
interface PageState { query: string; selectedId?: string; scrollIndex: number }
function migrateState(oldState: PageState, maxIndex: number): PageState {
return { ...oldState, scrollIndex: Math.max(0, Math.min(oldState.scrollIndex, maxIndex)) }
}
const state = migrateState({ query: 'API26', selectedId: 'doc-7', scrollIndex: 18 }, 12)
console.assert(state.query === 'API26')
console.assert(state.scrollIndex === 12)
模式变化只重排界面,搜索词、选中项和合法范围内的滚动位置继续保留。
现象、证据与动作
| 现象 | 先看什么 | 下一步动作 |
|---|---|---|
| 展开设备却布局拥挤 | 真实窗口宽度 | 按断点降级布局 |
| 窗口改变后内容跳回顶部 | 状态是否放在布局分支 | 提升到共享状态层 |
| 悬浮窗坐标偏移 | 坐标是否基于旧窗口 | 使用当前窗口坐标系 |
| 新型号需要大量特判 | 是否依赖设备名 | 删除型号分支,保留能力条件 |
三种做法怎么选
设备型号判断只能覆盖已知设备;姿态判断适合控制铰链相关交互;窗口断点直接回答“内容是否排得下”,对分屏、自由窗口和未来设备更稳定。推荐窗口宽度决定主结构,姿态只做可选增强。
能否封装和复用
把断点计算封装成纯函数,把页面状态放在布局分支之外,再让单列、双列、三列组件消费同一状态。这样列表页、详情页和编辑页都能复用相同布局策略。
最容易踩的三个误区
- 用设备型号或是否折叠决定列数,忽略分屏和自由窗口。
- 把筛选、滚动和选中状态分别存进三套布局组件,切换模式时重新初始化。
- 只截三张静态截图验收,没有拖动窗口穿越断点,因而漏掉抖动和重复重建。
如何避免问题再次出现
断点应来自统一设计令牌,并在临界值前后做连续窗口拖动测试。页面的 query、selectedId、scrollIndex 等业务状态由稳定的状态容器持有,布局组件只读取。对浮层、菜单和拖拽还要统一坐标系来源。新增设备时先跑窗口宽度矩阵,只有铰链遮挡等确实与姿态相关的行为才增加姿态条件。
本文验证到哪一层
本地断言覆盖 520、760、980 vp 三档布局,以及窗口缩小时滚动索引越界修正。真实铰链区域、系统安全区和窗口回调仍需在折叠屏或模拟环境中验证。
本文中的纯策略代码已在宿主 JavaScript 环境执行断言,用来验证计算、状态转换、排序或清单差异。当前本机仅有 API 24 SDK,且没有 HDC 真机,因此本文不把宿主断言描述为 API 26 工程编译或真机验证。涉及系统接口、设备形态、性能 Trace 或上架审核的结果,仍需在对应 API 26 SDK、设备和 AppGallery Connect 环境中完成端到端验收。
上线前检查清单
- 主布局依据当前窗口宽度
- 断点附近做连续拖拽测试
- 状态不存放在互斥布局分支
- 坐标使用当前窗口坐标系
- 单列到多列均有空数据和长文本测试
- 折叠、分屏、横竖屏完成设备验收
官方资料
折叠屏适配的核心不是识别更多姿态,而是让布局对真实可用空间负责。窗口宽度决定结构、姿态增强交互、业务状态独立保存,这三层分开后,适配代码会明显变少。
更多推荐



所有评论(0)