HarmonyOS5 便捷生活类——window弹窗打开时onBackPress失效(系列见主页)
来来来,加入官方CSDN班级并考证,拿鸿蒙礼盒!
加入下方官方CSDN班级,得鸿蒙礼盒
本期活动时间:2025年8月1日-12月31日
如有问题欢迎私聊我呀!
问题现象
当window弹窗不关闭的时候,跳转页面,通过侧滑手势返回无法触发页面的onBackPress进行页面返回。
问题弹窗代码示例参考如下:
import { window } from '@kit.ArkUI';
export class NYWindowDialog {
private static windowDialog: NYWindowDialog;
private dialogWindow: window.Window | undefined = undefined;
private name: string = 'XX_WINDOW_DIALOG'
private dialogConfig?: window.Configuration;
private params: object = new Object();
private winBgColor: string = '#40000000'
static getInstance(): NYWindowDialog {
if (!NYWindowDialog.windowDialog) {
NYWindowDialog.windowDialog = new NYWindowDialog()
}
return NYWindowDialog.windowDialog;
}
setParams(param: object): void {
this.params = param
}
getParams(): object {
return this.params
}
showWindowDialog(callback?: () => void): void {
this.dialogConfig = { name: this.name, windowType: window.WindowType.TYPE_DIALOG, ctx: getContext() }
if (this.dialogWindow) {
this.closeWindowDialog();
}
window.createWindow(this.dialogConfig, (string, newWindow: window.Window) => {
if (!newWindow) {
return
}
this.dialogWindow = newWindow;
newWindow.setWindowTouchable(true);
newWindow.setUIContent(this.params['page']).then(() => {
newWindow.setWindowBackgroundColor(this.winBgColor);
});
newWindow.showWindow(() => {
if (callback !== undefined) {
callback();
}
});
});
}
closeWindowDialog(callback?: () => void): void {
if (this.dialogWindow != null) {
this.dialogWindow.destroyWindow(() => {
if (callback !== undefined) {
callback();
}
});
}
}
setWindowBgColor(color: string): void {
this.winBgColor = color
}
}
背景知识
@ohos.window(窗口):窗口提供管理窗口的一些基础能力,包括对当前窗口的创建、销毁、各属性设置,以及对各窗口间的管理调度。通过Configuration接口设置窗口属性:
|
参数 |
说明 |
|---|---|
|
name |
窗口名字。 |
|
windowType |
窗口类型。 |
|
ctx |
当前应用上下文信息。不设置,则默认为空。FA模型下不需要使用该参数,即可创建子窗口,使用该参数时会报错。Stage模型必须使用该参数,用于创建悬浮窗、模态窗或系统窗口。 |
|
displayId |
当前物理屏幕id。不设置,则默认为-1,该参数应为整数。 |
|
parentId |
父窗口id。不设置,则默认为-1,该参数应为整数。 |
|
decorEnabled |
是否显示窗口装饰,仅在windowType为TYPE_DIALOG时生效。true表示显示,false表示不显示。此参数默认值为false。 |
|
title |
decorEnabled属性设置为true时,窗口的标题内容。标题显示区域最右端不超过系统三键区域最左端,超过部分以省略号表示。不设置,则默认为空字符串。 |
问题定位
窗口打开后除了不能侧滑返回以外,点击事件依旧能返回上一个页面。
- 考虑打开弹窗后,是否重写侧滑返回手势功能,禁止了侧滑返回。onBackPress生命周期内,返回true表示页面自己处理返回逻辑,不进行页面路由;返回false表示使用默认的路由返回逻辑,不设置返回值按照false处理。该生命周期当用户点击返回按钮时触发,仅@Entry装饰的自定义组件生效。
- 考虑模态弹窗问题。模态弹窗是一种强交互形式的弹窗,它会中断用户当前的操作流程,并要求用户必须做出响应才能继续其他操作。这种类型的弹窗通常用于需要向用户传达重要信息或确认的场景。查询@ohos.window(窗口)的窗口类型可知Configuration接口中windowType参数形式有以下几类:
|
参数 |
说明 |
|---|---|
|
TYPE_APP |
表示应用子窗口。 |
|
TYPE_SYSTEM_ALERT |
表示系统告警窗口。 |
|
TYPE_FLOAT |
表示悬浮窗。 |
|
TYPE_DIALOG |
表示模态窗口。 |
说明
其中:TYPE_DIALOG模态窗口页面设计是以模态方式显示,即在显示期间阻止与其他窗口的交互,故不支持侧滑操作。
分析结论
问题代码采用的TYPE_DIALOG模态窗口不支持侧滑返回操作,可以采用其它类型窗口。
修改建议
将模态弹窗更改为其它类型弹窗,选择方案如下:
- 方案一:通过创建子窗口的形式,实现弹窗效果,并实现侧滑返回效果。
- 修改EntryAbility页面配置。
// EntryAbility.ets import { UIAbility } from '@kit.AbilityKit'; import { window } from '@kit.ArkUI'; export default class EntryAbility extends UIAbility { // ... onWindowStageCreate(windowStage: window.WindowStage): void { windowStage.loadContent('pages/pageA', (err, data) => { // 全局使用 AppStorage.setOrCreate('windowStage', windowStage); }); } // ... } - 主页创建并调用子窗口。
// pageA.ets import window from '@ohos.window' import { common, Context } from '@kit.AbilityKit' import * as subWin from './subWindow'; // 导入命名路由页面(子窗口) import { BusinessError } from '@kit.BasicServicesKit'; @Entry @Component struct Index { // 全局使用 @State windowStage: window.WindowStage = AppStorage.get('windowStage') as window.WindowStage @State context: Context = getContext(this) as common.UIAbilityContext; build() { Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { Text('这是 page A') .fontSize(20) .margin({ bottom: 10 }) Button('点击打开子窗口') .onClick(() => { this.windowStage.createSubWindow('mySubWindow', (err, windowClass) => { try { windowClass.loadContentByName(subWin.entryName, (err: BusinessError) => { const errCode: number = err.code; if (errCode) { console.error(`Failed to load the content. Cause code: ${err.code}, message: ${err.message}`); return; } console.info('Succeeded in loading the content.'); // 设置子窗口左上角坐标 windowClass.moveWindowTo(0, 0) // 展示子窗口 windowClass.showWindow(); // 设置子窗口全屏化布局避让安全区 windowClass.setWindowLayoutFullScreen(false); }); } catch (exception) { console.error(`Failed to load the content. Cause code: ${exception.code}, message: ${exception.message}`); } }) }) } .backgroundColor(Color.Gray) .width('100%') .height('100%') } } - 自定义子窗口布局,并重写返回逻辑,侧滑销毁子窗口。
// subWindow.ets import { router, window } from '@kit.ArkUI'; export const entryName: string = 'subWindow'; class TmpClass { count: number = 10 } @Entry({ routeName: entryName }) @Component struct subWindow { @StorageProp('pageInfos') pageInfos: NavPathStack = new NavPathStack() onBackPress(): boolean | void { window.findWindow('mySubWindow').destroyWindow() // 销毁子窗口 } build() { Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { Text('这是子窗口') .fontSize(20) .margin({ bottom: 10 }) Button('点击跳转 Page B') .onClick(() => { router.pushUrl({ url: 'pages/PageB' }) }) .margin({ bottom: 15 }) Button('点击关闭子窗口') .onClick(() => { window.findWindow('mySubWindow').destroyWindow() // 销毁子窗口 }) } .backgroundColor(Color.White) .width('100%') .height('100%') } } - 创建跳转测试页面。
// page B import { window } from '@kit.ArkUI' @Entry @Component struct pageB { @State windowStage: window.WindowStage = AppStorage.get('windowStage') as window.WindowStage build() { Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { Text('这是 Page B,请左滑') .fontSize(20) .margin({ bottom: 10 }) .fontColor(Color.White) } .backgroundColor(Color.Green) .width('100%') .height('100%') } }
- 修改EntryAbility页面配置。
- 方案二:通过创建自定义组件实弹窗,并实现侧滑返回的效果。
详情案例参考文档:实现页面级弹出框的功能。
更多推荐
所有评论(0)