第5篇|窗口适配、安全区、暗色模式与隐私保护实战

📅 2026/7/2 7:54:43
第5篇|窗口适配、安全区、暗色模式与隐私保护实战
第5篇窗口适配、安全区、暗色模式与隐私保护实战摘要这篇不是泛泛而谈的“5 个小技巧”而是我在一个鸿蒙相册、地图、保险箱项目发布前集中处理的 5 个真实问题刘海屏遮挡、暗色模式不同步、多任务卡片泄露相册缩略图、保险箱离开后仍保持解锁、平板布局继续沿用手机底部导航。它们单看都不算大 bug但一旦进入上架或真机联调阶段几乎每一个都会掉分。我的处理原则只有一条不要硬编码不要只修当前页面要把系统状态收进统一状态源再按页面职责消费。在这轮收口里我把问题拆成了五类先给结论表检查项真实翻车方式根因修复动作安全区状态栏或手势条遮挡内容用固定像素写死间距从 Window 获取 avoid area存入 AppStorage暗色模式系统切黑后页面仍是浅色页面各自维护颜色状态在 EntryAbility 统一监听再用StorageLink下发相册防窥多任务卡片暴露最近照片进入和离开相册没有管理防窥状态进入相册订阅离开相册解除保险箱锁定切走再切回仍是解锁态锁定状态只在页面内存里挂着离开 Tab 立即回收解锁态多设备布局平板上仍是手机底部导航布局没有按宽度分发用窗口宽度切分手机和大屏布局1. 安全区不是 UI 微调而是系统输入这个问题最先暴露在真机上顶部标题被状态栏压住底部 Tab 又被手势条顶上来。模拟器里看不明显一换刘海屏和全面屏就暴露。我一开始也想过直接补padding({ top: 44 })之类的固定值但这种写法只能在一台设备上看起来“差不多”换设备马上翻车。更稳的做法是把系统窗口数据当成状态源在EntryAbility统一取一次再分发给页面。// EntryAbility.etsonWindowStageCreate(windowStage:window.WindowStage):void{constwinwindowStage.getMainWindowSync();constpropswin.getWindowProperties();AppStorage.setOrCreate(superImage.windowWidthPx,props.windowRect.width);AppStorage.setOrCreate(superImage.windowHeightPx,props.windowRect.height);constsystemAreawin.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);AppStorage.setOrCreate(superImage.safeAreaTopPx,systemArea.topRect?.height??0);AppStorage.setOrCreate(superImage.safeAreaBottomPx,systemArea.bottomRect?.height??0);}页面里不要自己猜安全区而是直接消费这几个状态StorageLink(superImage.safeAreaTopPx)privatesafeAreaTopPx:number0;StorageLink(superImage.safeAreaBottomPx)privatesafeAreaBottomPx:number0;这样顶栏、底栏、全屏图片区都能用同一套数据不会出现 A 页修好了、B 页还在被挡的情况。2. 暗色模式跟不跟随关键不在颜色值在状态归谁管第二个问题更常见系统已经切到深色页面还是浅色背景或者主页面跟随了地图、弹窗、卡片却各用各的颜色形成“阴阳界面”。这类 bug 本质上不是配色没写完而是主题状态没有统一入口。我的处理方式是仍然在EntryAbility监听系统窗口状态变化把是否深色写进AppStorage页面只消费不自己判断。onWindowStageCreate(windowStage:window.WindowStage):void{constwinwindowStage.getMainWindowSync();constpropswin.getWindowProperties();AppStorage.setOrCreate(superImage.isDarkMode,props.isDarkMode);win.on(windowEvent,(event){if(eventwindow.WindowEvent.DARK_MODE_CHANGED){constupdatedPropswin.getWindowProperties();AppStorage.setOrCreate(superImage.isDarkMode,updatedProps.isDarkMode);}});}页面侧只保留一份状态入口StorageLink(superImage.isDarkMode)privateisDarkMode:booleanfalse;然后背景色、文字色、地图模式都跟着这一份状态走Column(){// 页面内容}.backgroundColor(this.isDarkMode?#1a1a2e:#f5f5f5).foregroundColor(this.isDarkMode?#e0e0e0:#333333)privatemapOptions:mapCommon.MapOptions{dayNightMode:mapCommon.DayNightMode.AUTO,}这一步的关键不是“写了深色主题”而是保证整个应用只认一份主题状态。3. 相册防窥要跟页面切换联动不能只在相册页里写一个开关第三个问题是在隐私巡检时暴露的用户刚看过私密照片切到后台或任务卡片时缩略图可能被带出来。这种问题平时不一定有人提但一旦真机演示很容易直接判定为高风险体验。我的处理不是给相册页单独加一个“防窥”按钮而是把它和导航状态联动。进入相册时订阅防窥状态离开相册时解除。import{dlpAntiPeep}fromkit.DeviceSecurityKit;privategalleryAntiPeepSubscribed:booleanfalse;StateprivategalleryAntiPeepActive:booleanfalse;