HarmonyOS鸿蒙Next中创建悬浮窗之后,设置setWindowTouchable(false)之后,悬浮窗上的按钮也不响应
HarmonyOS鸿蒙Next中创建悬浮窗之后,设置setWindowTouchable(false)之后,悬浮窗上的按钮也不响应 代码如下:
创建悬浮窗代码
onCreateShareWind() {
// 1.创建悬浮窗。
let windowClass: window.Window | null = null;
let config: window.Configuration = {
name: 'shareWindow', windowType: window.WindowType.TYPE_FLOAT, ctx: this.getUIContext().getHostContext()
};
window.createWindow(config, (err, data) => {
let errCode: number = err.code;
if (errCode) {
Logger.error(tag, `Failed to create the shareWindow. Cause: ${JSON.stringify(err)}`);
return;
}
windowClass = data;
// 2.悬浮窗窗口创建成功后,设置悬浮窗的位置、大小及相关属性等。
try {
let displayClass = display.getDefaultDisplaySync();
windowClass.moveWindowTo(0, 0).catch(() => {
// TODO: Implement error handling.
});
windowClass.resize(displayClass.width, displayClass.height).catch(() => {
// TODO: Implement error handling.
});
} catch (error) {
// TODO: Implement error handling.
}
windowClass.setWindowTouchable(false).catch(() => {
// TODO: Implement error handling.
});
windowClass.setWindowFocusable(false).catch(() => {
// TODO: Implement error handling.
}); // 禁止获焦
// 3.为悬浮窗加载对应的目标页面。
windowClass.setUIContent('pages/SharePage', (err1) => {
let errCode: number = err1.code;
if (errCode) {
Logger.error(tag, `Failed to load the content. Cause: ${JSON.stringify(err1)}`);
return;
}
try {
(windowClass as window.Window).setWindowBackgroundColor('#00000000');
} catch (error) {
// TODO: Implement error handling.
}
ConfService.closeContext?.hideAbility().catch(() => {
// TODO: Implement error handling.
});
// 3.显示悬浮窗。
(windowClass as window.Window).showWindow().catch(() => {
});
});
});
}
页面代码
build() {
Stack({ alignContent: Alignment.Top }) {
Row() {
Text('正在共享屏幕')
Button($r('app.string.StopSharing'))
.onClick(() => {
Logger.info(tag, `StopSharing`)
})
}
.backgroundColor(Color.White)
}
.height('100%')
.width('100%')
.borderWidth( 5)
.enabled(this.isEnabled)
.borderColor(Color.Red)
}
我想实现的是全屏悬浮窗,窗口上按钮可以响应事件,其他区域不响应,能透传到其他应用窗口。
目前问题:
其他应用窗口可以响应,但按钮点击没有任何反应
更多关于HarmonyOS鸿蒙Next中创建悬浮窗之后,设置setWindowTouchable(false)之后,悬浮窗上的按钮也不响应的实战教程也可以访问 https://www.itying.com/category-93-b0.html
开发者你好,
设置了setWindowTouchable及setWindowFocusable之后,就代表窗口不可获焦不可触摸,不会响应任何事件。窗口要么可触摸要么不可触摸,如果设置了窗口不可触摸不可获焦,则不响应任何事件是正常情况。可使用两个窗口的实现对应效果。
更多关于HarmonyOS鸿蒙Next中创建悬浮窗之后,设置setWindowTouchable(false)之后,悬浮窗上的按钮也不响应的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
希望后续能够改进,能够真正解决我的诉求
尊敬的开发者,您好!麻烦您提供以下需求信息:
请问您是在什么样的业务场景中使用该能力,交互流程是怎样的,在哪一个环节遇到了问题?另外请您说明能力不满足可能带来的影响:什么时间用到?是否高频?有无三方库可以做到?若提供该能力,是否会造成大工作量返工?请您注意提供的内容不要包含您或第三方的非公开信息,如给您带来不便,敬请谅解。
核心结论
setWindowTouchable(false) = 整个悬浮窗完全不接收触摸 → 按钮必然失效你要的效果是:悬浮窗全屏 + 背景穿透 + 只有按钮能点击
正确方案只有一种:
不要用 setWindowTouchable (false),改用 UI 属性:hitTestBehavior: HitTestMode.HIT_TEST_NONE
一、修复步骤(100% 解决)
1. 删除这两行(关键!)
ts
// 删掉这两行!!!
windowClass.setWindowTouchable(false)
windowClass.setWindowFocusable(false)
2. 悬浮窗保持默认:可触摸、可点击
ts
// 什么都不用写,默认就是 touchable: true
3. 在你的悬浮窗页面根节点,设置:
ts
.hitTestBehavior(HitTestMode.HIT_TEST_NONE)
作用:根布局不接收触摸,触摸直接穿透到下面
4. 给 Button 单独设置:
ts
.hitTestBehavior(HitTestMode.HIT_TEST_SELF)
作用:只有按钮能接收点击
二、最终正确页面代码
ts
@Entry
@Component
struct SharePage {
build() {
Stack() {
Row() {
Text('正在共享屏幕')
Button('停止共享')
.onClick(() => {
console.log('✅ 按钮可点击!')
})
// 关键:按钮自己能响应
.hitTestBehavior(HitTestMode.HIT_TEST_SELF)
}
.backgroundColor(Color.White)
}
.width('100%')
.height('100%')
// 关键:根布局穿透触摸
.hitTestBehavior(HitTestMode.HIT_TEST_NONE)
}
}
三、悬浮窗创建代码(保持不变,只删 touchable 即可)
ts
windowClass.setWindowTouchable(false) // ❌ 删除
windowClass.setWindowFocusable(false) // ❌ 删除
四、最终效果(你想要的)
- 悬浮窗全屏
- 背景穿透点击(下面 APP 可操作)
- 悬浮窗上的按钮可以正常响应
五、官方文档

为啥网站无法访问
找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17,
你好,可以使用 触摸测试控制 HitTestMode,
1、将悬浮窗口设置为 HitTestMode.Transparent: 实现事件穿透。
Stack()
.hitTestBehavior(HitTestMode.Transparent)
2、将窗口里的按钮设置为 HitTestMode.BLOCK_HIERARCHY: 自身和子节点响应触摸测试,阻止所有优先级较低的兄弟节点和父节点参与触摸测试。
@Entry
@Component
struct Index {
build() {
Stack() {
Row()
.height('100%')
.width('100%')
.onClick(() => {
console.log('----底部响应了---')
})
.backgroundColor('#80154fde')
Stack() {
Text('Text')
.height(100)
.width(100)
.backgroundColor('#f0f')
.hitTestBehavior(HitTestMode.BLOCK_HIERARCHY)
.gesture(
TapGesture()
.onAction(() => {
console.log('悬浮窗上的按钮点击了')
})
)
}
.height('100%')
.width('100%')
.backgroundColor('#1aa54c4c')
.hitTestBehavior(HitTestMode.Transparent)
}
}
}
setWindowTouchable(true/false)方法是设置窗口是否为可触状态。true表示可触;false表示不可触。您设置了false是关闭触摸了,设置成true试试。
设置true之后就不能透传的底层了,无法点击到窗口下层的应用
设置 setWindowTouchable(false) 后,整个窗口(包括其中的按钮)都不再接收触摸事件,因此按钮无法响应。要实现“按钮可点击,其余区域穿透”的效果,应使用 setTouchableAreas 接口。该方法允许你指定窗口内的一组矩形区域,只有这些区域内的触摸事件会被窗口处理,区域外的触摸会自动穿透到下层的应用窗口,无需再将整个窗口设为不可触摸。
操作步骤如下:
- 保持窗口默认可触摸(不调用
setWindowTouchable(false))。 - 获取按钮在窗口中的位置与尺寸(可通过
onAreaChange等事件)。 - 调用
setTouchableAreas设置矩形区域(坐标相对于窗口左上角)。
示例关键代码:
// 假设已获得按钮在窗口中的左、上、宽、高
let rect: window.Rect = { left: 100, top: 50, width: 200, height: 80 };
windowClass.setTouchableAreas([rect]);
按钮以外的区域触摸会直接透传到下层,按钮可正常响应,同时 setWindowFocusable(false) 可继续使用以避免抢占焦点。


