基于ArkTS语言的OpenHarmony APP应用开发:窗口管理 原创
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 | 表示应用子窗口。<br>模型约束: 此接口仅可在FA模型下使用。 |
TYPE_SYSTEM_ALERT | 1 | 表示系统告警窗口。 |
TYPE_INPUT_METHOD<sup>9+</sup> | 2 | 表示输入法窗口。<br>模型约束: 此接口仅可在Stage模型下使用。<br>系统接口: 此接口为系统接口。 |
TYPE_STATUS_BAR<sup>9+</sup> | 3 | 表示状态栏窗口。<br>模型约束: 此接口仅可在Stage模型下使用。<br>系统接口: 此接口为系统接口。 |
TYPE_PANEL<sup>9+</sup> | 4 | 表示通知栏。<br>模型约束: 此接口仅可在Stage模型下使用。<br>系统接口: 此接口为系统接口。 |
TYPE_KEYGUARD<sup>9+</sup> | 5 | 表示锁屏。<br>模型约束: 此接口仅可在Stage模型下使用。<br>系统接口: 此接口为系统接口。 |
TYPE_VOLUME_OVERLAY<sup>9+</sup> | 6 | 表示音量条。<br>模型约束: 此接口仅可在Stage模型下使用。<br>系统接口: 此接口为系统接口。 |
TYPE_NAVIGATION_BAR<sup>9+</sup> | 7 | 表示导航栏窗口。<br>模型约束: 此接口仅可在Stage模型下使用。<br>系统接口: 此接口为系统接口。 |
TYPE_FLOAT<sup>9+</sup> | 8 | 表示悬浮窗。<br>模型约束: 此接口仅可在Stage模型下使用。<br>需要权限: ohos.permission.SYSTEM_FLOAT_WINDOW |
TYPE_WALLPAPER<sup>9+</sup> | 9 | 表示壁纸。<br>模型约束: 此接口仅可在Stage模型下使用。<br>系统接口: 此接口为系统接口。 |
TYPE_DESKTOP<sup>9+</sup> | 10 | 表示桌面。<br>模型约束: 此接口仅可在Stage模型下使用。<br>系统接口: 此接口为系统接口。 |
TYPE_LAUNCHER_RECENT<sup>9+</sup> | 11 | 表示多任务中心。<br>模型约束: 此接口仅可在Stage模型下使用。<br>系统接口: 此接口为系统接口。 |
TYPE_LAUNCHER_DOCK<sup>9+</sup> | 12 | 表示桌面Dock栏。<br>模型约束: 此接口仅可在Stage模型下使用。<br>系统接口: 此接口为系统接口。 |
TYPE_VOICE_INTERACTION<sup>9+</sup> | 13 | 表示智慧语音。<br>模型约束: 此接口仅可在Stage模型下使用。<br>系统接口: 此接口为系统接口。 |
TYPE_POINTER<sup>9+</sup> | 14 | 表示鼠标。<br>模型约束: 此接口仅可在Stage模型下使用。<br>系统接口: 此接口为系统接口。 |
TYPE_FLOAT_CAMERA<sup>9+</sup> | 15 | 表示相机类型悬浮窗。<br>模型约束: 此接口仅可在Stage模型下使用。<br>系统接口: 此接口为系统接口。 |
TYPE_DIALOG<sup>9+</sup> | 16 | 表示模态窗口。<br>模型约束: 此接口仅可在Stage模型下使用。<br>系统接口: 此接口为系统接口。 |
TYPE_SCREENSHOT<sup>9+</sup> | 17 | 表示截屏窗口。<br>模型约束: 此接口仅可在Stage模型下使用。<br>系统接口: 此接口为系统接口。 |
2.1.3、window.Configuration
创建子窗口或系统窗口时的参数。
系统能力: SystemCapability.WindowManager.WindowManager.Core
名称 | 类型 | 必填 | 说明 |
---|---|---|---|
name | string | 是 | 窗口名字。 |
windowType | WindowType | 是 | 窗口类型。 |
ctx | BaseContext | 否 | 当前应用上下文信息。不设置,则默认为空。<br>FA模型下不需要使用该参数,即可创建子窗口。<br>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<void> | 无返回结果的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<void> | 是 | 回调函数。 |
错误码:
以下错误码的详细介绍请参见窗口错误码。
错误码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<void> | 是 | 回调函数。 |
返回值:
类型 | 说明 |
---|---|
Promise<void> | 无返回结果的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<void> | 是 | 异常响应回调。 |
返回值:
类型 | 说明 |
---|---|
Promise<void> | 异常返回结果。 |
错误码:
以下错误码的详细介绍请参见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。
在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界面。如下所示:
点击Run 'npm install'
,让DevEco Studio安装相关依赖包。
重新点击菜单栏上的“Build” -> “Rebuild Project”。出现如下错误:
点击上图红色框部分,安装相关服务。
重新点击菜单栏上的“Build” -> “Rebuild Project”,编译成功。
4.3、安装程序
点击“entry”按钮,将项目程序安装到设备端。如下图所示:
如果出现下述报错,表示无法安装。如图所示:
点击上图红色框的蓝色字体,弹出"Project Structure"对话框,点击"Apply",再点击"OK"。如图所示:
重新点击“entry”按钮,将项目程序安装到设备端。