提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

窗口管理在部分程序中也尤为重要,本章知识点在鸿蒙开发中,也较为难理解,极其需要深究!


提示:以下是本篇文章正文内容,下面案例可供参考

1.窗口管理:

1.1窗口开发概述

1.1.1窗口模块的定义(什么是窗口

窗口模块用于在同一块物理屏幕上,提供多个应用界面显示、交互的机制。

  • 应用开发者而言,窗口模块提供了界面显示交互能力
  • 终端用户而言,窗口模块提供了控制应用界面的方式。
  • 整个操作系统而言,窗口模块提供了不同应用界面的组织管理逻辑

1.1.2窗口模块的用途(窗口的作用

提供应用和系统界面的窗口对象。

组织不同窗口的显示关系,即维护不同窗口间的叠加层次和位置属性。

提供窗口动效。

指导输入事件分发。

提供窗口装饰(默认关闭,需要在系统配置里或线下指令调换配置来打开,才有此功能)

1.1.3基本概念(窗口的类型

HarmonyOS的窗口模块将窗口界面分为系统窗口应用窗口两种基本类型。

  • 系统窗口系统窗口指完成系统特定功能的窗口。如音量条、壁纸、通知栏、状态栏、导航栏等。
  • 应用窗口应用窗口区别于系统窗口,指与应用显示相关的窗口。根据显示内容的不同,应用窗口又分为应用主窗口应用子窗口两种类型。
    • 应用主窗口:应用主窗口用于显示应用界面,会在"任务管理界面"显示。
    • 应用子窗口:应用子窗口用于显示应用的弹窗、悬浮窗等辅助窗口,不会在"任务管理界面"显示。应用子窗口的生命周期跟随应用主窗口。

1.1.4实现原理

当前窗口的实现和开发与应用开发模型相关联,不同模型下的接口功能略有区别。当前应用开发模型分为FA模型Stage模型

  • FA(Feature Ability)模型:HarmonyOS早期版本开始支持的模型,已经不再主推。
  • Stage模型:是目前主推且会长期演进的模型。

1.1.5约束与限制

应用主窗口与子窗口存在大小限制,宽度范围:[320, 2560],高度范围:[240, 2560],单位为vp。

1.2管理应用窗口(Stage模型)

1.2.1基本概念

  • 窗口沉浸式能力:指对状态栏导航栏等系统窗口进行控制,减少状态栏导航栏等系统界面的突兀感,从而使用户获得最佳体验的能力。

沉浸式能力只在应用主窗口作为全屏窗口时生效。通常情况下,应用子窗口(弹窗、悬浮窗口等辅助窗口)无法使用沉浸式能力。

  • 悬浮窗:全局悬浮窗口是一种特殊的应用窗口,具备在应用主窗口和对应Ability退至后台后仍然可以在前台显示的能力。

悬浮窗口可以用于应用退至后台后,使用小窗继续播放视频,或者为特定的应用创建悬浮球等快速入口。应用在创建悬浮窗口前,需要申请对应的权限

1.2.2场景介绍

在Stage模型下,管理应用窗口的典型场景有:

  • 设置应用主窗口属性及目标页面
  • 设置应用子窗口属性及目标页面
  • 体验窗口沉浸式能力
  • 设置悬浮窗

1.2.3接口说明

实例名WindowStage 

接口名getMainWindow(callback:AsyncCallback<Window>): void

描述 获取WindowStage实例下的主窗口。此接口仅可在Stage模型下使用。

实例名WindowStage 

接口名loadContent(path: string, callback: AsyncCallback<void>): void

描述 为当前WindowStage的主窗口加载具体页面。此接口仅可在Stage模型下使用。

实例名WindowStage 

接口名createSubWindow(name:string,callback:AsyncCallback<Window>): void

描述 创建子窗口。此接口仅可在Stage模型下使用。

实例名window静态方法 

接口名createWindow(config:Configuration,callback:AsyncCallback<Window>): void

描述 创建子窗口或系统窗口。-config:创建窗口时的参数。

实例名Window 

接口名setUIContent(path: string, callback: AsyncCallback<void>): void

描述 为当前窗口加载具体页面。

实例名Window 

接口名
setWindowBrightness(brightness:number,callback:AsyncCallback<void>): void

描述 设置屏幕亮度值。

实例名Window 

接口名setWindowTouchable(isTouchable:boolean,callback:AsyncCallback<void>): void

描述 设置窗口是否为可触状态。

实例名Window 

接口名moveWindowTo(x:number,y:number,callback:AsyncCallback<void>): void

描述 移动当前窗口位置。

实例名Window 

接口名
resize(width: number, height: number, callback: AsyncCallback<void>): void

描述 改变当前窗口大小。

实例名Window 

接口名
setWindowSystemBarEnable(names: Array<'status'|'navigation'>): Promise<void>

描述 设置导航栏、状态栏是否显示。

实例名Window 

接口名
showWindow(callback: AsyncCallback<void>): void

描述 显示当前窗口。

实例名Window 

接口名
showWindow(callback: AsyncCallback<void>): void

描述 显示当前窗口。

实例名Window 

接口名
on(type: 'touchOutside', callback: Callback<void>): void

描述 开启本窗口区域外的点击事件的监听。

实例名Window 

接口名
destroyWindow(callback: AsyncCallback<void>): void

描述 销毁当前窗口。

1.2.4设置应用主窗口

开发步骤

1.获取应用主窗口。

通过getMainWindow接口获取应用主窗口。

2.设置主窗口属性。

可设置主窗口的背景色、亮度值、是否可触等多个属性,开发者可根据需要选择对应的接口。本示例以设置“是否可触”属性为例。

3.为主窗口加载对应的目标页面。

通过loadContent接口加载主窗口的目标页面。

三者代码如下:

import UIAbility from '@ohos.app.ability.UIAbility';

export default class EntryAbility extends UIAbility {

    onWindowStageCreate(windowStage) {

        // 1.获取应用主窗口。

        let windowClass = null;

        windowStage.getMainWindow((err, data) => {

            if (err.code) {

                console.error('Failed to obtain the main window. Cause: ' + JSON.stringify(err));

                return;

            }

            windowClass = data;

            console.info('Succeeded in obtaining the main window. Data: ' + JSON.stringify(data));

            // 2.设置主窗口属性。以设置"是否可触"属性为例。

            let isTouchable = true;

            windowClass.setWindowTouchable(isTouchable, (err) => {

                if (err.code) {

                    console.error('Failed to set the window to be touchable. Cause:' + JSON.stringify(err));

                    return;

                }

                console.info('Succeeded in setting the window to be touchable.');

            })

        })

        // 3.为主窗口加载对应的目标页面。

        windowStage.loadContent("pages/page2", (err) => {

            if (err.code) {

                console.error('Failed to load the content. Cause:' + JSON.stringify(err));

                return;

            }

            console.info('Succeeded in loading the content.');

        });

    }

};

1.2.5设置应用子窗口

开发步骤

1.创建应用子窗口。

通过createSubWindow接口创建应用子窗口。

2.设置子窗口属性。

子窗口创建成功后,可以改变其大小、位置等,还可以根据应用需要设置窗口背景色、亮度等属性。

3.加载显示子窗口的具体内容。

通过setUIContentshowWindow接口加载显示子窗口的具体内容。

4.销毁子窗口。

当不再需要某些子窗口时,可根据具体实现逻辑,使用destroyWindow接口销毁子窗口。

四者代码如下:

import UIAbility from '@ohos.app.ability.UIAbility';

let windowStage_ = null;

let sub_windowClass = null;

export default class EntryAbility extends UIAbility {

    showSubWindow() {

        // 1.创建应用子窗口。

        windowStage_.createSubWindow("mySubWindow", (err, data) => {

            if (err.code) {

                console.error('Failed to create the subwindow. Cause: ' + JSON.stringify(err));

                return;

            }

            sub_windowClass = data;

            console.info('Succeeded in creating the subwindow. Data: ' + JSON.stringify(data));

            // 2.子窗口创建成功后,设置子窗口的位置、大小及相关属性等。

            sub_windowClass.moveWindowTo(300, 300, (err) => {

                if (err.code) {

                    console.error('Failed to move the window. Cause:' + JSON.stringify(err));

                    return;

                }

                console.info('Succeeded in moving the window.');

            });

            sub_windowClass.resize(500, 500, (err) => {

                if (err.code) {

                    console.error('Failed to change the window size. Cause:' + JSON.stringify(err));

                    return;

                }

                console.info('Succeeded in changing the window size.');

            });

            // 3.为子窗口加载对应的目标页面。

            sub_windowClass.setUIContent("pages/page3", (err) => {

                if (err.code) {

                    console.error('Failed to load the content. Cause:' + JSON.stringify(err));

                    return;

                }

                console.info('Succeeded in loading the content.');

                // 3.显示子窗口。

                sub_windowClass.showWindow((err) => {

                    if (err.code) {

                        console.error('Failed to show the window. Cause: ' + JSON.stringify(err));

                        return;

                    }

                    console.info('Succeeded in showing the window.');

                });

            });

        })

    }

    destroySubWindow() {

        // 4.销毁子窗口。当不再需要子窗口时,可根据具体实现逻辑,使用destroy对其进行销毁。

        sub_windowClass.destroyWindow((err) => {

            if (err.code) {

                console.error('Failed to destroy the window. Cause: ' + JSON.stringify(err));

                return;

            }

            console.info('Succeeded in destroying the window.');

        });

    }

    onWindowStageCreate(windowStage) {

        windowStage_ = windowStage;

        // 开发者可以在适当的时机,如主窗口上按钮点击事件等,创建子窗口。并不一定需要在onWindowStageCreate调用,这里仅作展示

        this.showSubWindow();

    }

    onWindowStageDestroy() {

        // 开发者可以在适当的时机,如子窗口上点击关闭按钮等,销毁子窗口。并不一定需要在onWindowStageDestroy调用,这里仅作展示

        this.destroySubWindow();

    }

};

1.2.6体验窗口沉浸式能力

开发步骤

1.获取应用主窗口。

通过getMainWindow接口获取应用主窗口。

2.实现沉浸式效果。

调用setWindowSystemBarEnable接口,设置导航栏、状态栏不显示,从而达到沉浸式效果。

3.加载显示沉浸式窗口的具体内容。

通过loadContent接口加载沉浸式窗口的具体内容。

三者代码如下:

import UIAbility from '@ohos.app.ability.UIAbility';

export default class EntryAbility extends UIAbility {

    onWindowStageCreate(windowStage) {

        // 1.获取应用主窗口。

        let windowClass = null;

        windowStage.getMainWindow((err, data) => {

            if (err.code) {

                console.error('Failed to obtain the main window. Cause: ' + JSON.stringify(err));

                return;

            }

            windowClass = data;

            console.info('Succeeded in obtaining the main window. Data: ' + JSON.stringify(data));

            // 2.实现沉浸式效果:设置导航栏、状态栏不显示。

            let names = [];

            windowClass.setWindowSystemBarEnable(names, (err) => {

                if (err.code) {

                    console.error('Failed to set the system bar to be visible. Cause:' + JSON.stringify(err));

                    return;

                }

                console.info('Succeeded in setting the system bar to be visible.');

            });

        })

        // 3.为沉浸式窗口加载对应的目标页面。

        windowStage.loadContent("pages/page2", (err) => {

            if (err.code) {

                console.error('Failed to load the content. Cause:' + JSON.stringify(err));

                return;

            }

            console.info('Succeeded in loading the content.');

        });

    }

};

1.2.7设置悬浮窗

开发步骤

前提条件:创建WindowType.TYPE_FLOAT即悬浮窗类型的窗口,需要申请ohos.permission.SYSTEM_FLOAT_WINDOW权限,配置方式请参见配置文件权限声明

1.创建悬浮窗。

通过window.createWindow接口创建悬浮窗类型的窗口。

2.对悬浮窗进行属性设置等操作。

悬浮窗窗口创建成功后,可以改变其大小、位置等,还可以根据应用需要设置悬浮窗背景色、亮度等属性。

3.加载显示悬浮窗的具体内容。

通过setUIContentshowWindow接口加载显示悬浮窗的具体内容。

4.销毁悬浮窗。

当不再需要悬浮窗时,可根据具体实现逻辑,使用destroyWindow接口销毁悬浮窗。

import UIAbility from '@ohos.app.ability.UIAbility';

import window from '@ohos.window';

export default class EntryAbility extends UIAbility {

    onWindowStageCreate(windowStage) {

        // 1.创建悬浮窗。

        let windowClass = null;

        let config = {name: "floatWindow", windowType: window.WindowType.TYPE_FLOAT, ctx: this.context};

        window.createWindow(config, (err, data) => {

            if (err.code) {

                console.error('Failed to create the floatWindow. Cause: ' + JSON.stringify(err));

                return;

            }

            console.info('Succeeded in creating the floatWindow. Data: ' + JSON.stringify(data));

            windowClass = data;

            // 2.悬浮窗窗口创建成功后,设置悬浮窗的位置、大小及相关属性等。

            windowClass.moveWindowTo(300, 300, (err) => {

                if (err.code) {

                    console.error('Failed to move the window. Cause:' + JSON.stringify(err));

                    return;

                }

                console.info('Succeeded in moving the window.');

            });

            windowClass.resize(500, 500, (err) => {

                if (err.code) {

                    console.error('Failed to change the window size. Cause:' + JSON.stringify(err));

                    return;

                }

                console.info('Succeeded in changing the window size.');

            });

            // 3.为悬浮窗加载对应的目标页面。

            windowClass.setUIContent("pages/page4", (err) => {

                if (err.code) {

                    console.error('Failed to load the content. Cause:' + JSON.stringify(err));

                    return;

                }

                console.info('Succeeded in loading the content.');

                // 3.显示悬浮窗。

                windowClass.showWindow((err) => {

                    if (err.code) {

                        console.error('Failed to show the window. Cause: ' + JSON.stringify(err));

                        return;

                    }

                    console.info('Succeeded in showing the window.');

                });

            });

            // 4.销毁悬浮窗。当不再需要悬浮窗时,可根据具体实现逻辑,使用destroy对其进行销毁。

            windowClass.destroyWindow((err) => {

                if (err.code) {

                    console.error('Failed to destroy the window. Cause: ' + JSON.stringify(err));

                    return;

                }

                console.info('Succeeded in destroying the window.');

            });

        });

    }

};

1.3管理应用窗口(FA模型)

基本概念窗口沉浸式能力:指对状态栏、导航栏等系统窗口进行控制,减少状态栏导航栏等系统界面的突兀感,从而使用户获得最佳体验的能力。

沉浸式能力只在应用主窗口作为全屏窗口时生效。通常情况下,应用子窗口(弹窗、悬浮窗口等辅助窗口)无法使用沉浸式能力。

1.3.1场景介绍

在FA模型下,管理应用窗口的典型场景有:

  • 设置应用子窗口属性及目标页面
  • 体验窗口沉浸式能力

1.3.2接口说明

实例名window静态方法

接口名createWindow(config:Configuration,callback:AsyncCallback<Window>): void

描述 创建子窗口。-config:创建窗口时的参数。

实例名window静态方法

接口名findWindow(name: string): Window

描述 查找name所对应的窗口。

实例名Window

接口名setUIContent(path: string, callback: AsyncCallback<void>): void

描述 为当前窗口加载具体页面内容。

实例名Window

接口名moveWindowTo(x:number,y:number,callback:AsyncCallback<void>):void

描述 移动当前窗口。

实例名Window

接口名setWindowBrightness(brightness:number,callback:AsyncCallback<void>): void

描述 设置屏幕亮度值。

实例名Window

接口名resize(width:number,height:number,callback:AsyncCallback<void>):void

描述 改变当前窗口大小。

实例名Window

接口名
setWindowSystemBarEnable(names:Array<'status'|'navigation'>):Promise<void>

描述 设置导航栏、状态栏是否显示。

实例名Window

接口名showWindow(callback: AsyncCallback<void>): void

描述 显示当前窗口。

实例名Window

接口名on(type: 'touchOutside', callback: Callback<void>): void

描述 开启本窗口区域外的点击事件的监听。

实例名Window

接口名destroyWindow(callback: AsyncCallback<void>): void

描述 销毁当前窗口。

1.3.3设置应用子窗口

开发步骤

1.创建/获取子窗口对象。

可以通过window.createWindow接口创建子窗口。

也可以通过window.findWindow接口来查找已经创建的窗口从而得到子窗口。

   代码如下:

import window from '@ohos.window';

   let windowClass = null;

   // 方式一:创建子窗口。

   let config = {name: "subWindow", windowType: window.WindowType.TYPE_APP};

   window.createWindow(config, (err, data) => {

       if (err.code) {

           console.error('Failed to create the subWindow. Cause: ' + JSON.stringify(err));

           return;

       }

       console.info('Succeeded in creating subWindow. Data: ' + JSON.stringify(data));

       windowClass = data;

   });

   // 方式二:查找得到子窗口。

   try {

       windowClass = window.findWindow('subWindow');

   } catch (exception) {

       console.error('Failed to find the Window. Cause: ' + JSON.stringify(exception));

   }

2.设置子窗口属性。

子窗口创建成功后,可以改变其大小、位置等,还可以根据应用需要设置窗口背景色、亮度等属性。

代码如下:

// 移动子窗口位置。

windowClass.moveWindowTo(300, 300, (err) => {

  if (err.code) {

    console.error('Failed to move the window. Cause:' + JSON.stringify(err));

    return;

  }

  console.info('Succeeded in moving the window.');

});

// 改变子窗口大小。

windowClass.resize(500, 500, (err) => {

  if (err.code) {

    console.error('Failed to change the window size. Cause:' + JSON.stringify(err));

    return;

  }

  console.info('Succeeded in changing the window size.');

});

3.加载显示子窗口的具体内容。

使用setUIContentshowWindow接口加载显示子窗口的具体内容。

代码如下:

// 为子窗口加载对应的目标页面。

windowClass.setUIContent("pages/page2", (err) => {

    if (err.code) {

        console.error('Failed to load the content. Cause: ' + JSON.stringify(err));

        return;

    }

    console.info('Succeeded in loading the content.');

    // 显示子窗口。

    windowClass.showWindow((err) => {

     if (err.code) {

            console.error('Failed to show the window. Cause: ' + JSON.stringify(err));

            return;

        }

        console.info('Succeeded in showing the window.');

    });

});

4.销毁子窗口。

当不再需要某些子窗口时,可根据场景的具体实现逻辑,使用destroyWindow接口销毁子窗口。

代码如下:

// 销毁子窗口。当不再需要某些子窗口时,可根据场景的具体实现逻辑,使用destroy接口销毁子窗口。

windowClass.destroyWindow((err) => {

    if (err.code) {

        console.error('Failed to destroy the subwindow. Cause:' + JSON.stringify(err));

        return;

    }

    console.info('Succeeded in destroying the subwindow.');

});

1.3.4体验窗口沉浸式能力

开发步骤

1.获取主窗口对象。

说明

沉浸式能力需要在成功获取应用主窗口对象的前提下进行。

确保应用内最后显示的窗口为主窗口,然后再使用window.getLastWindow接口来获取得到主窗口。

代码如下:

import window from '@ohos.window';

let mainWindowClass = null;

// 获取主窗口。

window.getLastWindow(this.context,(err, data) => {

  if (err.code) {

    console.error('Failed to get the subWindow. Cause: ' + JSON.stringify(err));

    return;

  }

  console.info('Succeeded in getting subWindow. Data: ' + JSON.stringify(data));

  mainWindowClass = data;

});

2.实现沉浸式效果。
调用setWindowSystemBarEnable接口,设置导航栏、状态栏不显示,从而达到沉浸式效果。

代码如下:

// 实现沉浸式效果:设置导航栏、状态栏不显示。

let names = [];

mainWindowClass.setWindowSystemBarEnable(names, (err) => {

  if (err.code) {

    console.error('Failed to set the system bar to be visible. Cause:' + JSON.stringify(err));

    return;

  }

  console.info('Succeeded in setting the system bar to be visible.');

});

3.加载显示沉浸式窗口的具体内容。

使用setUIContent和showWindow接口加载显示沉浸式窗口的具体内容。

代码如下:

// 为沉浸式窗口加载对应的目标页面。

mainWindowClass.setUIContent("pages/page3", (err) => {

    if (err.code) {

        console.error('Failed to load the content. Cause: ' + JSON.stringify(err));

        return;

    }

    console.info('Succeeded in loading the content.');

    // 显示沉浸式窗口。

    mainWindowClass.showWindow((err) => {

        if (err.code) {

            console.error('Failed to show the window. Cause: ' + JSON.stringify(err));

            return;

        }

        console.info('Succeeded in showing the window.');

    });

});

总结

提示:这里对文章进行总结:
以上就是今天要讲的内容,本文介绍了窗口管理的知识点,它会提供应用和系统界面的窗口管理。

Logo

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

更多推荐