HarmonyOS 7 新特性(十九)|闪控窗与闪控球多形态任务

HarmonyOS 7 强化闪控窗与闪控球联动:窗口可自由拖动、侧边暂存,并与闪控球一键切换。本文讨论多形态窗口的状态归属、权限、焦点与恢复边界。
购物比价、搜题、翻译、通话和计时都希望在用户使用其他应用时保留轻入口。闪控球适合极简状态与恢复入口,闪控窗承载更完整的实时信息,主窗口负责配置和复杂任务。
真正的工程难点不是把窗口做小,而是三个形态之间切换时不丢任务、不重复执行、不抢焦点,也不泄露敏感内容。
一、先选择正确窗口方案
应用内普通子窗口实现简单,不需要特殊权限;系统悬浮窗适用于少量被允许的全局场景;PC/2in1 可评估多 UIAbility;闪控球需要 ohos.permission.USE_FLOAT_BALL,并受 API 和场景审核约束。
权限必须与核心功能匹配。不能因为想做一个悬浮按钮就申请全局能力,也不能在用户拒绝后循环弹出授权。
二、领域任务独立于窗口
type WindowMode = 'MAIN' | 'FLOAT_VIEW' | 'FLOAT_BALL'
interface FloatingTaskState {
taskId: string
taskType: 'translation' | 'compare' | 'timer'
status: 'IDLE' | 'RUNNING' | 'PAUSED' | 'DONE' | 'FAILED'
mode: WindowMode
version: number
updatedAt: number
}
窗口只渲染任务快照,不拥有翻译、通话或下载任务。销毁闪控窗只是改变展示形态,不能终止领域任务;任务结束后则要通知所有形态收口。
三、三种形态各有职责
主窗口:首次授权、参数设置、历史记录和复杂编辑。
闪控窗:当前结果、实时进度、暂停、继续和返回主窗等少量动作。
闪控球:状态点、计时或未读提示,以及恢复闪控窗的单一动作。
如果闪控球需要滚动、输入和多级导航,就已经超出其职责;如果闪控窗遮住大面积内容,也应引导回主窗。

四、使用协调器串行化窗口操作
class FloatingWindowCoordinator {
private currentMode: WindowMode = 'MAIN'
private transition: Promise<void> = Promise.resolve()
switchTo(mode: WindowMode): Promise<void> {
this.transition = this.transition.then(async () => {
if (this.currentMode === mode) return
await this.hide(this.currentMode)
await this.show(mode)
this.currentMode = mode
})
return this.transition
}
}
快速连点可能同时触发“打开闪控窗”和“收成闪控球”。串行队列保证前一次形态切换完成后再处理下一次,避免出现两个窗口。
五、窗口位置不能直接保存像素
拖动时要避让状态栏、刘海、手势区域、键盘和系统侧边栏。屏幕旋转、分辨率或显示器改变后重新约束坐标。
interface NormalizedPosition {
xRatio: number
yRatio: number
edge: 'left' | 'right' | 'none'
}
function restorePosition(p: NormalizedPosition, safe: Rect): Point {
return clampToSafeArea({
x: safe.left + safe.width * p.xRatio,
y: safe.top + safe.height * p.yRatio
}, safe)
}
保存比例和吸附边,而不是绝对像素,才能在不同窗口尺寸下合理恢复。
六、侧边暂存仍要可发现
暂存后保留足够的露出区域和明确状态,点击恢复。避免与系统返回手势冲突,也不要遮挡其他应用的关键按钮。首次使用可以轻提示一次,之后依赖稳定位置和图形表达。
七、焦点管理优先于视觉效果
闪控窗出现时不应抢走用户正在其他应用输入的焦点。只有用户主动点击输入区域才申请焦点;隐藏时归还。键盘弹出后重新计算可用区域,不能把输入框推到屏幕外。
同一应用内主窗和子窗可使用窗口焦点切换能力,但必须限制在用户明确动作之后。
八、隐私状态要单独设计
锁屏、投屏、录屏和后台时,根据任务类型隐藏联系人、搜索内容和翻译原文。闪控球只显示中性图标或数量,不显示敏感正文。
function toPublicSnapshot(state: FloatingTaskState,
privacy: PrivacyContext): FloatingViewModel {
if (privacy.locked || privacy.screenShared) {
return { title: '任务进行中', detail: '', sensitive: false }
}
return buildDetailedViewModel(state)
}
九、恢复顺序是任务优先
进程重启后先读取 taskId 与版本,向领域服务确认任务仍有效,再决定恢复主窗、闪控窗还是闪控球。若任务已经完成,只展示结果通知;若权限被撤回,回到主窗说明,而不是重新创建悬浮入口。
async function restoreFloatingEntry(saved: SavedWindowState) {
const task = await taskRepository.get(saved.taskId)
if (!task || isTerminal(task.status)) return showResultNotification(task)
if (!permission.canUseFloatBall()) return openMainWindow(task.taskId)
return coordinator.switchTo(saved.preferredMode)
}
十、测试矩阵
- 权限允许、拒绝、撤回和系统不支持;
- 主窗、闪控窗、闪控球快速连续切换;
- 横竖屏、分屏、自由窗口、键盘和多显示器;
- 锁屏、投屏、录屏与敏感任务;
- 进程回收、任务完成、失败和重新登录;
- 无障碍焦点、触控尺寸与减少动态效果。
describe('FloatingWindowCoordinator', () => {
it('never shows two floating modes together', async () => {
await Promise.all([
coordinator.switchTo('FLOAT_VIEW'),
coordinator.switchTo('FLOAT_BALL')
])
expect(windowDriver.visibleFloatingCount()).toBe(1)
})
})
十一、上线清单
- 选择了最小权限的窗口方案;
- 领域任务与窗口生命周期完全分离;
- 形态切换串行且可重复调用;
- 坐标使用安全区域和归一化恢复;
- 焦点只在用户动作后切换;
- 锁屏与投屏具有隐私快照;
- 恢复时先验证任务和权限;
- 不支持场景可以回到主窗口。

结语
闪控窗与闪控球的价值,是让任务在多应用之间保持可见,而不是让应用永久悬浮。把任务设为单一事实源,用窗口协调器管理形态,再处理权限、焦点、坐标和隐私,才能得到稳定的多任务体验。
官方参考
- HarmonyOS 7 新能力一览:https://developer.huawei.com/consumer/cn/features/
- 全局悬浮窗方案:https://developer.huawei.com/consumer/cn/doc/doccenter-dev-faq/faqs-multi-device-deployment-8
更多推荐



所有评论(0)