加入下方官方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时,窗口的标题内容。标题显示区域最右端不超过系统三键区域最左端,超过部分以省略号表示。不设置,则默认为空字符串。

问题定位

窗口打开后除了不能侧滑返回以外,点击事件依旧能返回上一个页面。

  1. 考虑打开弹窗后,是否重写侧滑返回手势功能,禁止了侧滑返回。onBackPress生命周期内,返回true表示页面自己处理返回逻辑,不进行页面路由;返回false表示使用默认的路由返回逻辑,不设置返回值按照false处理。该生命周期当用户点击返回按钮时触发,仅@Entry装饰的自定义组件生效。
  2. 考虑模态弹窗问题。模态弹窗是一种强交互形式的弹窗,它会中断用户当前的操作流程,并要求用户必须做出响应才能继续其他操作。这种类型的弹窗通常用于需要向用户传达重要信息或确认的场景。查询@ohos.window(窗口)的窗口类型可知Configuration接口中windowType参数形式有以下几类:

参数

说明

TYPE_APP

表示应用子窗口。

TYPE_SYSTEM_ALERT

表示系统告警窗口。

TYPE_FLOAT

表示悬浮窗。

TYPE_DIALOG

表示模态窗口。

说明

其中:TYPE_DIALOG模态窗口页面设计是以模态方式显示,即在显示期间阻止与其他窗口的交互,故不支持侧滑操作。

分析结论

问题代码采用的TYPE_DIALOG模态窗口不支持侧滑返回操作,可以采用其它类型窗口。

修改建议

将模态弹窗更改为其它类型弹窗,选择方案如下:

  • 方案一:通过创建子窗口的形式,实现弹窗效果,并实现侧滑返回效果。
    1. 修改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);
      });
      }
      // ...
      }

    2. 主页创建并调用子窗口。
      
          
      // 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%')
      }
      }

    3. 自定义子窗口布局,并重写返回逻辑,侧滑销毁子窗口。
      
          
      // 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%')
      }
      }

    4. 创建跳转测试页面。
      
          
      // 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%')
      }
      }

  • 方案二:通过创建自定义组件实弹窗,并实现侧滑返回的效果。

    详情案例参考文档:实现页面级弹出框的功能

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐