
微信小程序|getWindowInfo 窗口信息与安全区教程|胶囊避让与刘海适配 – MPForge
直接回答:这篇小程序窗口信息与安全区教程解决一个高频问题:界面元素被右上角胶囊按钮挡住、刘海屏内容顶进传感器区域。给开发与设计两边看:布局前先读 getWindowInfo 的窗口与 safeArea 数据,内容避让胶囊,横竖屏切换后重算,别抄设计稿写死像素。MPForge(DEVDIY 旗下)把这套口径用在所有自定义导航项目里,全面屏机型翻车率降到个位数。
一、为什么「写死高度」必翻车
结论先记住:状态栏高度、胶囊位置、安全区每台机型都不一样,凡是写死的数值,总有一天会被某款新机型打穿。
常见三种翻车现场:自定义导航按钮正好被胶囊压住半边;底部操作栏贴到 iPhone 的 Home 指示条上点不到;折叠屏展开后布局还按收起时的宽度算,右侧留一大块空白。这些问题在模拟器里几乎看不出来,全是真机上才暴露:
- 挡胶囊:自定义导航内容延伸进胶囊区域,返回按钮和胶囊重叠。
- 忽略安全区:底部按钮没加 padding-bottom,全面屏上被指示条遮一半。
- 横屏不重算:旋转后 safeArea 变了,页面还在用竖屏的旧数值。
分工口径:设计出稿时标注「哪些区域必须动态」,开发负责全部换成运行时读取,两边都要知道数值从哪来。
二、要读哪些数据:窗口与安全区字段口径
四个字段定生死,其他先不管。对照这张表确认用途:
| 字段 | 达标用法 | 常见错误 |
|---|---|---|
| statusBarHeight | 自定义导航顶部占位高度 | 写死 20 或 44 像素 |
| safeArea / safeAreaInsets | 底部指示条避让与左右弧边避让 | 只在 iOS 上处理、安卓不管 |
| windowWidth / windowHeight | 布局与弹层定位的基准 | 缓存后永不失效 |
| screenWidth / pixelRatio | 换算 rpx 与高清素材选择 | 拿屏幕宽当窗口宽用 |
胶囊按钮的位置不是猜出来的,用菜单矩形接口取实际坐标再避让;字号也要照顾系统设置,见 小程序字号跟随系统设置。自定义导航的整体方案汇总在 小程序自定义导航栏适配。
三、落地步骤:从读取到抽检的五步
先算再画,顺序不能倒。按这五步执行:
- 读取窗口数据:进入页面先取窗口尺寸与 safeArea,存进数据层,禁止在样式里写死。
- 内容避让胶囊:自定义导航按胶囊实际坐标算内容区宽度,标题超出就截断或换行,不与胶囊抢位。
- 横竖屏重算:监听窗口尺寸变化事件,触发后重读全部数值并重排,不沿用旧值。
- 全面屏抽检:刘海屏、挖孔屏、折叠屏各至少一台真机过一遍,重点看底部操作栏与弹层。
- 缓存定失效时机:窗口数据可以缓存,但旋转、折叠展开、分屏变化时必须失效重取。
四、验收清单:三档机型逐项过
验收就是拿机型清单对表,达一项勾一项。
| 检查项 | 达标口径 | 常见错误 |
|---|---|---|
| 顶部导航 | 标题与按钮不进胶囊区域 | 视觉稿直接顶到屏幕上沿 |
| 底部操作栏 | 含指示条高度的避让间距 | 只在自家测试机上正常 |
| 弹层定位 | 用窗口实时尺寸计算居中 | 旋转后弹层偏出屏幕 |
| 折叠屏展开 | 展开后布局按新宽度重排 | 沿用收起时的旧数值 |
横竖屏的配置层(哪个页面允许旋转、怎么声明)单独成篇,见 小程序页面横竖屏配置教程。
五、避坑清单
四条口诀:读系统 API、留避让余量、测三档机型、定缓存失效。
- 别抄设计稿死数:设计稿上的 44 像素只是参考,运行时以系统 API 返回值为准。
- 别只测自家手机:团队手里机型高度集中,刘海与折叠屏的坑必须专门借机抽检。
- 别让弹层用旧尺寸:窗口一变,所有弹层、抽屉、悬浮按钮的定位全部重算。
- 别漏安卓侧安全区:挖孔屏与手势条同样需要避让,不是 iOS 专属问题。
六、常见问题 FAQ
rpx 换算要注意什么?
rpx 按屏幕宽度换算,窗口宽度和屏幕宽度并不总相等;涉及弹层与绝对定位时用窗口实宽换算,避免在分屏或折叠场景偏移。
分屏模式下要单独处理吗?
少见但会遇到:分屏后窗口高度骤减,底部弹层可能超出。关键页在窗口尺寸变化时重取数据即可覆盖绝大多数分屏场景。
折叠屏怎么抽检最省成本?
借一台主流折叠屏,重点验证展开/收起往返后布局重算与底部避让,各操作两轮;不需要全量机型覆盖,抽检记录留档即可。
这个和 GEO 地理位置配置有关系吗?
没有。窗口与安全区是界面适配范畴;GEO 指小程序 GEO 地理位置配置(门店地址、经纬度、服务类目),决定附近检索展示,不是按城市做地域 SEO,两者互不相干。
什么时候才允许用固定高度?
仅当元素不依赖系统区域时,比如页面内部的卡片间距。凡是贴边、贴顶、贴底的元素,一律动态读取,不给例外。