[文章]基于ArkTS语言的OpenHarmony APP应用开发:窗口管理

阅读量0
0
1

1、程序介绍

本示例展示了在应用主窗口中创建和拉起子窗口,以及窗口跳转等功能。

本案例已在OpenHarmony凌蒙派-RK3568开发板验证通过,具体代码可参考:https://gitee.com/Lockzhiner-Electronics/lockzhiner-rk3568-openharmony/tree/master/samples/d06_WindowManage

API接口:9

2、知识准备

2.1、@ohos.window

窗口提供管理窗口的一些基础能力,包括对当前窗口的创建、销毁、各属性设置,以及对各窗口间的管理调度。

详情请参看:@ohos.window(窗口)

2.2.1、导入模块

import window from '@ohos.window'

2.1.2、window.WindowType

窗口类型枚举。

系统能力: SystemCapability.WindowManager.WindowManager.Core

名称 说明
TYPE_APP 0 表示应用子窗口。 模型约束:此接口仅可在FA模型下使用。
TYPE_SYSTEM_ALERT 1 表示系统告警窗口。
TYPE_INPUT_METHOD^9+^ 2 表示输入法窗口。 模型约束:此接口仅可在Stage模型下使用。 系统接口:此接口为系统接口。
TYPE_STATUS_BAR^9+^ 3 表示状态栏窗口。 模型约束:此接口仅可在Stage模型下使用。 系统接口:此接口为系统接口。
TYPE_PANEL^9+^ 4 表示通知栏。 模型约束:此接口仅可在Stage模型下使用。 系统接口:此接口为系统接口。
TYPE_KEYGUARD^9+^ 5 表示锁屏。 模型约束:此接口仅可在Stage模型下使用。 系统接口:此接口为系统接口。
TYPE_VOLUME_OVERLAY^9+^ 6 表示音量条。 模型约束:此接口仅可在Stage模型下使用。 系统接口:此接口为系统接口。
TYPE_NAVIGATION_BAR**^9+^ 7 表示导航栏窗口。 模型约束:此接口仅可在Stage模型下使用。 系统接口:此接口为系统接口。
TYPE_FLOAT^9+^ 8 表示悬浮窗。 模型约束:此接口仅可在Stage模型下使用。 需要权限:ohos.permission.SYSTEM_FLOAT_WINDOW
TYPE_WALLPAPER^9+^ 9 表示壁纸。 模型约束:此接口仅可在Stage模型下使用。 系统接口:此接口为系统接口。
TYPE_DESKTOP^9+^ 10 表示桌面。 模型约束:此接口仅可在Stage模型下使用。 系统接口:此接口为系统接口。
TYPE_LAUNCHER_RECENT^9+^ 11 表示多任务中心。 模型约束:此接口仅可在Stage模型下使用。 系统接口:此接口为系统接口。
TYPE_LAUNCHER_DOCK^9+^ 12 表示桌面Dock栏。 模型约束:此接口仅可在Stage模型下使用。 系统接口:此接口为系统接口。
TYPE_VOICE_INTERACTION^9+^ 13 表示智慧语音。 模型约束:此接口仅可在Stage模型下使用。 系统接口:此接口为系统接口。
TYPE_POINTER^9+^ 14 表示鼠标。 模型约束:此接口仅可在Stage模型下使用。 系统接口:此接口为系统接口。
TYPE_FLOAT_CAMERA^9+^ 15 表示相机类型悬浮窗。 **模型约束:此接口仅可在Stage模型下使用。 系统接口:此接口为系统接口。
TYPE_DIALOG^9+^ 16 表示模态窗口。 模型约束:此接口仅可在Stage模型下使用。 系统接口:此接口为系统接口。
TYPE_SCREENSHOT^9+^ 17 表示截屏窗口。 模型约束:此接口仅可在Stage模型下使用。 系统接口:此接口为系统接口。

2.1.3、window.Configuration

创建子窗口或系统窗口时的参数。

系统能力: SystemCapability.WindowManager.WindowManager.Core

名称 类型 必填 说明
name string 窗口名字。
windowType WindowType 窗口类型。
ctx BaseContext 当前应用上下文信息。不设置,则默认为空。 FA模型下不需要使用该参数,即可创建子窗口。 Stage模型下需要使用该参数,用于创建系统窗口。
displayId number 当前物理屏幕id。不设置,则默认为-1。
parentId number 父窗口id。不设置,则默认为-1。

2.1.4、window.createWindow

// 创建子窗口或者系统窗口,使用callback异步回调。
createWindow(config: Configuration, callback: AsyncCallback<Window>): void
// 创建子窗口或者系统窗口,使用Promise异步回调。
createWindow(config: Configuration): Promise<Window>

系统能力: SystemCapability.WindowManager.WindowManager.Core

其中,参数定义如下:

参数名 类型 必填 说明
config Configuration 创建窗口时的参数。
callback AsyncCallback<Window> 回调函数。返回当前创建的窗口对象。

其中,错误码定义如下:

错误码ID 错误信息
1300001 Repeated operation.
1300006 This window context is abnormal.

2.1.5、window.loadContent

// 为当前窗口加载与LocalStorage相关联的具体页面内容,使用callback异步回调。
loadContent(path: string, storage: LocalStorage, callback: AsyncCallback<void>): void
// 为当前窗口加载与LocalStorage相关联的具体页面内容,使用Promise异步回调。
loadContent(path: string, storage: LocalStorage): Promise<void>

模型约束:此接口仅可在Stage模型下使用。

系统能力: SystemCapability.WindowManager.WindowManager.Core

参数:

参数名 类型 必填 说明
path string 设置加载页面的路径。
storage LocalStorage 存储单元,为应用程序范围内的可变状态属性和非可变状态属性提供存储。

返回值:

类型 说明
Promise> 无返回结果的Promise对象。

错误码:

以下错误码的详细介绍请参见窗口错误码。

错误码ID 错误信息
1300002 This window state is abnormal.
1300003 This window manager service works abnormally.

2.1.6、window.showWindow

// 显示当前窗口,使用callback异步回调。
showWindow(callback: AsyncCallback<void>): void
// 显示当前窗口,使用Promise异步回调。
showWindow(): Promise<void>

系统能力:SystemCapability.WindowManager.WindowManager.Core

参数:

参数名 类型 必填 说明
callback AsyncCallback> 回调函数。

错误码:

以下错误码的详细介绍请参见窗口错误码。

错误码ID 错误信息
1300002 This window state is abnormal.

2.1.7、window.destroyWindow

// 销毁当前窗口,使用callback异步回调。
destroyWindow(callback: AsyncCallback<void>): void
// 销毁当前窗口,使用Promise异步回调。
destroyWindow(): Promise<void>

系统能力:SystemCapability.WindowManager.WindowManager.Core

参数:

参数名 类型 必填 说明
callback AsyncCallback> 回调函数。

返回值:

类型 说明
Promise> 无返回结果的Promise对象。

错误码:

以下错误码的详细介绍请参见窗口错误码。

错误码ID 错误信息
1300002 This window state is abnormal.
1300003 This window manager service works abnormally.

示例:

let promise = windowClass.destroyWindow();
promise.then(()=> {
    console.info('Succeeded in destroying the window.');
}).catch((err)=>{
    console.error('Failed to destroy the window. Cause: ' + JSON.stringify(err));
});

2.2、@ohos.router

本模块提供通过不同的url访问不同的页面,包括跳转到应用内的指定页面、用应用内的某个页面替换当前页面、返回上一页面或指定的页面等。

2.2.1、导入模块

import router from '@ohos.router'

2.2.2、router.pushUrl

// 跳转到应用内的指定页面。
pushUrl(options: RouterOptions): Promise<void>
// 跳转到应用内的指定页面。
pushUrl(options: RouterOptions, callback: AsyncCallback<void>): void
// 跳转到应用内的指定页面。
pushUrl(options: RouterOptions, mode: RouterMode): Promise<void>
// 跳转到应用内的指定页面。
pushUrl(options: RouterOptions, mode: RouterMode, callback: AsyncCallback<void>): void

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名 类型 必填 说明
options RouterOptions 跳转页面描述信息。
mode RouterMode 跳转页面使用的模式。
callback AsyncCallback> 异常响应回调。

返回值:

类型 说明
Promise> 异常返回结果。

错误码:

以下错误码的详细介绍请参见ohos.router(页面路由)错误码。

错误码ID 错误信息
100001 if UI execution context not found.
100002 if the uri is not exist.
100003 if the pages are pushed too much.

2.2.3、router.back

// 返回上一页面或指定的页面。
back(options?: RouterOptions): void

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名 类型 必填 说明
options RouterOptions 返回页面描述信息,其中参数url指路由跳转时会返回到指定url的界面,如果页面栈上没有url页面,则不响应该情况。如果url未设置,则返回上一页,页面栈里面的page不会回收,出栈后会被回收。

3、程序解析

3.1、Index.ets

Index.ets作为主页面,主要创建5个按键,并负责构建相对应的处理函数。

3.1.1、创建子窗口

创建按钮,并通过Window.createWindow()创建子窗口句柄。

private createSubWindow() {
    // 窗口配置
    let config = {name: "alertWindow", windowType: window.WindowType.TYPE_SYSTEM_ALERT, ctx: getContext()}
​
    // 如果之前已有,则销毁
    this.destroySubWindow()
​
    try {
      // 创建子窗口
      let promise = window.createWindow(config)
      promise.then((data) => {
        this.subWindow = data                     // 将子窗口句柄转交给subWindow
        this.subWindow.setWindowFocusable(false)  // 设置是否支持切换焦点窗口
        this.subWindow.resize(750, 480)         // 设置子窗口的高宽
        this.subWindow.moveWindowTo(0, 0)         // 移动窗口位置
        this.status = 'createSubWindow 成功'
      }).catch((err)=>{
        this.status = 'createSubWindow 失败2:' + JSON.stringify(err)
      });
    } catch (exception) {
      this.status = 'createSubWindow 失败1: ' + JSON.stringify(exception)
    }
}
​
// 页面显示
build() {
    Column({space: 10}) {
      Button("创建子窗口")
        .onClick(() => {
          this.createSubWindow()
        })
    }
}

3.1.2、加载内容

创建按钮,并通过Window.loadContent()将页面加载到子窗口。

private loadContent(path: string) {
    if (this.subWindow != null) {
      let storage = new LocalStorage()
​
      storage.setOrCreate('storageSimpleProp', 121)
      try {
        // subWindow加载第二个页面page/Second
        let promise = this.subWindow.loadContent(path, storage)
        promise.then(() => {
          this.status = 'loadContent 成功: '
        }).catch((err) => {
          this.status = 'loadContent 失败: ' + JSON.stringify(err)
        })
      } catch (exception) {
        this.status = 'loadContent 失败: ' + JSON.stringify(exception)
      }
    } else {
      this.status = 'subWindow没有创建'
    }
}
​
// 页面显示
build() {
    Column({space: 10}) {
      Button("加载内容")
        .onClick(() => {
          this.loadContent("pages/Second")
        })
    }
}

3.1.3、显示子窗口

创建按钮,并通过Window.showWindow()将子窗口设置为显示状态。

private showSubWindow() {
    if (this.subWindow != null) {
      // 显示subWindow页面
      this.subWindow.showWindow((err) => {
        if (err.code) {
          this.status = 'showSubWindow失败: ' + JSON.stringify(err)
          return;
        }
        this.status = 'showSubWindow成功'
      })
    } else {
      this.status = 'subWindow没有创建'
    }
}
​
// 页面显示
build() {
    Column({space: 10}) {
      Button("显示子窗口")
        .onClick(() => {
          this.showSubWindow()
        })
    }
}

3.1.4、销毁子窗口

创建按钮,并通过Window.destroyWindow()将子窗口句柄销毁。

private destroySubWindow() {
    if (this.subWindow != null) {
      // 销毁页面句柄
      this.subWindow.destroyWindow((err) => {
        if (err.code) {
          this.status = 'destroySubWindow失败: ' + JSON.stringify(err)
        } else {
          this.status = 'destroySubWindow 成功'
        }
      })
    } else {
      this.status = 'subWindow没有创建'
    }
}
​
// 页面显示
build() {
    Column({space: 10}) {
      Button("销毁子窗口")
        .onClick(() => {
          this.destroySubWindow()
        })
    }
}

3.1.5、打开第二页

通过router.pushUrl()跳转到第二页面。

// 页面显示
build() {
    Column({space: 10}) {
      Button("打开第二页")
        .onClick(() => {
          router.pushUrl({
            url: 'pages/Second'
          })
        })
    }
}

3.2、Second.ets

3.2.1、创建pages/Second.ets

在左侧栏Project,点击"pages",右击选择"New -> ArkTS File",创建Second.ets。
创建第二页面.png
在Second.ets文件输入源代码。

import window from '@ohos.window'
import router from '@ohos.router'// 第二个页面
@Entry @Component struct Second {
​
  build() {
    Column({space: 10}) {
      Text('第二个页面')
        .fontSize(50)
        .width('100%')
        .textAlign(TextAlign.Center)
​
      Button('返回上一页')
        .onClick(() => {
          router.back(); // 返回上一页,当前页面会销毁
        })
    }
    .size({width: '100%', height: '100%'})
  }
}

3.2.2、登记pages/Second.ets

打开entry/src/main/resources/base/profile/main_pages.json文件。将pages/Second添加到文件中。

{
  "src": [
    "pages/Index",
    "pages/Second"
  ]
}

4、项目编译

4.1、打开项目

打开DevEco Studio,再打开自定义通知项目。

4.2、编译程序

点击菜单栏上的“Build” -> "Rebuild Project"。如果出现无法编译,则注意查看Event Log界面。如下所示:

question_npm_install.png

点击Run 'npm install',让DevEco Studio安装相关依赖包。

重新点击菜单栏上的“Build” -> "Rebuild Project"。出现如下错误:
question_root_module.png
点击上图红色框部分,安装相关服务。

重新点击菜单栏上的“Build” -> "Rebuild Project",编译成功。
rebuild_project_successful.png

4.3、安装程序

点击“entry”按钮,将项目程序安装到设备端。如下图所示:
heap_install_to_device.png
如果出现下述报错,表示无法安装。如图所示:
heap_install_failed.png

点击上图红色框的蓝色字体,弹出"Project Structure"对话框,点击"Apply",再点击"OK"。如图所示:
project_structure.png

重新点击“entry”按钮,将项目程序安装到设备端。
entry_successful.png

5、运行结果

5.1、主页面

运行结果-主界面.jpg

5.2、子窗口

运行结果-子窗口.jpg

5.3、跳转窗口

运行结果-页面跳转.jpg

回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友