HarmonyOS:新建一个window的详细过程和步骤

前言:我们项目中有用到全局的悬浮框,看了很多博客和文档,鸿蒙的全局悬浮框也是在新建的window上加载一个悬浮框的,我这一节主要是来讲如何新建一个window的方法,下一节讲在window上新建一个悬浮框的方法。
系统window api可自行参考,不理解的方法,也可以参考系统Api。

1.获取window需要的windowStage方法

创建window的方法,windowStage.createSubWindow(‘mySubWindow’, (err: BusinessError, data) ,windowStage如何来呢?
我们是在首页才需要创建,因此在入口类EntryAbility的地方,需要存储windowStage

AppStorage.setOrCreate("windowStage", windowStage);

获取windowStage的方法,在你需要创建window的页面,获取一下就ok了

@State windowStage: window.WindowStage = AppStorage.get('windowStage') as window.WindowStage;
2.创建新的window
export  class FlowWindowOptions{
 //windowStage
  windowStage: window.WindowStage;
  //新建window名字
  windowName: string;
  //window加载内容页面路径
  windowShowInContentName: string;
  //window背景颜色
  windowBackGroundColor?: string;
  //新建window大小
  windowInitSize?: Size;
  //新建window坐标
  windowInitPostion?:Position;
  //系统的导航栏高度,用来控制window的边界
  windowNavHeight?:number;
  //系统的底部tabbar栏高度,用来控制window的边界
  windowTabbarHeight?:number;
  constructor(windowStage: window.WindowStage, windowName: string, windowShowInContentName: string,
    windowBackGroundColor?: string,windowInitPostion?:Position,windowInitSize?:Size,windowNavHeight?:number,windowTabbarHeight?:number) {
    this.windowStage = windowStage;
    this.windowName = windowName;
    this.windowShowInContentName = windowShowInContentName;
    this.windowBackGroundColor = windowBackGroundColor;
    this.windowInitPostion = windowInitPostion;
    this.windowInitSize = windowInitSize;
    this.windowNavHeight = windowNavHeight;
    this.windowTabbarHeight = windowTabbarHeight;
  }

这是我自定义的新建window的option类,主要是给window传参数的,

创建window,需要一个新的window名字,参数中需要一个window的名字,用来区分不同的window
this.windowOptions.windowStage.createSubWindow(this.windowOptions.windowName, (err, win) => {
    
})

设置window的初始位置,window窗口可以在屏幕的任何位置,但是我处理了一些边界问题,只能放在导航栏之下,以及底部导航栏以上位置,初始化的时候,如果position设置的不合理,会恢复默认位置,因为我们的项目悬浮框初始放在右侧,所以我会用屏幕的宽度-window的宽度

win.moveWindowTo(display.getDefaultDisplaySync().width - vp2px(positionX), vp2px(positionY), (err) => {

设置window的大小,窗口初始化一个大小,后续可以更改窗口的大小

win.resize(window_w, window_h, (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.');
      });

设置window加载的内容,窗口构建之后就需要加载窗口的内容,setUIContent就是加载窗口内容的方法,这个是个路径

win.setUIContent(this.windowOptions.windowShowInContentName, (err: BusinessError) => {
        if (err.code) {
          console.error('Failed to load the content. Cause:' + JSON.stringify(err));
          return;
        }
        win.setWindowBackgroundColor(this.windowOptions.windowBackGroundColor?this.windowOptions.windowBackGroundColor:'#12ffff00')

        console.info('Succeeded in loading the content.');
        // 显示悬浮窗。
        win.showWindow((err: BusinessError) => {
          if (err.code) {
            console.error('Failed to show the window. Cause: ' + JSON.stringify(err));
            return;
          }
          console.info('Succeeded in showing the window.');
        });
      });
销毁window

这是销毁window的方法,比如某个界面不需要显示悬浮框就可以销毁,或者隐藏它

// 自定义销毁悬浮窗方法
  destroyFloatWindow(windowName:string) {
    // 用windowClass调用destroyWindow销毁悬浮窗
    window.findWindow(windowName).destroyWindow((err) => {
      if (err.code) {
        console.error('Failed to destroy the window. Cause: ' + JSON.stringify(err));
        return;
      }
      console.info('Succeeded in destroying the window.');
    });
  }

完整的代码:

import { display, window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';

export  class FlowWindowOptions{
  windowStage: window.WindowStage;
  windowName: string;
  windowShowInContentName: string;
  windowBackGroundColor?: string;
  windowInitSize?: Size;
  windowInitPostion?:Position;
  windowNavHeight?:number;
  windowTabbarHeight?:number;
  constructor(windowStage: window.WindowStage, windowName: string, windowShowInContentName: string,
    windowBackGroundColor?: string,windowInitPostion?:Position,windowInitSize?:Size,windowNavHeight?:number,windowTabbarHeight?:number) {
    this.windowStage = windowStage;
    this.windowName = windowName;
    this.windowShowInContentName = windowShowInContentName;
    this.windowBackGroundColor = windowBackGroundColor;
    this.windowInitPostion = windowInitPostion;
    this.windowInitSize = windowInitSize;
    this.windowNavHeight = windowNavHeight;
    this.windowTabbarHeight = windowTabbarHeight;
  }
}
export  class FloatWindowUtil {
  private windowOptions: FlowWindowOptions;
  constructor(windowOptions: FlowWindowOptions) {
    this.windowOptions = windowOptions;
  }
  // 定义windowClass变量,用来接收创建的悬浮窗
  // 自定义创建悬浮窗方法
  createFloatWindow() {
    if (this.windowOptions==undefined){
      console.error('windowOptions 不能为空');
      return
    }
    // 窗口类型设置为window.WindowType.TYPE_FLOAT
    // 创建悬浮窗
    this.windowOptions.windowStage.createSubWindow(this.windowOptions.windowName, (err, win) => {
      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(win));
      let window_w = StyleConstants.WINDOW_SIZE.width as number;
      let window_h = StyleConstants.WINDOW_SIZE.height as number;

      if (this.windowOptions.windowInitSize) {
        if (this.windowOptions.windowInitSize.width <= 0) {
          console.error('window 宽度不能设置为0,使用默认宽度 ');
        }else if (this.windowOptions.windowInitSize.width + window_w >display.getDefaultDisplaySync().width) {
          console.error('window 宽度设置太大,使用默认宽度 ');
        }else {
          window_w = this.windowOptions.windowInitSize.width;
        }
        if (this.windowOptions.windowInitSize.height <= 0) {
          console.error('window 高度不能设置为0,使用默认高度 ');
        }else if (this.windowOptions.windowInitSize.height + window_h >display.getDefaultDisplaySync().height) {
          console.error('window 高度设置太大,使用默认高度');
        }else {
          window_h = this.windowOptions.windowInitSize.height;
        }
      }
      let positionY :number = StyleConstants.WINDOW_POSTION.y as number;
      if (this.windowOptions.windowInitPostion){
        if (this.windowOptions.windowInitPostion.y) {
          positionY = this.windowOptions.windowInitPostion.y as number
        }
      }
      let navHeight: number = StyleConstants.WINDOW_NAVGATION_H;
      if (this.windowOptions.windowNavHeight){
        if (navHeight > StyleConstants.WINDOW_NAVGATION_H * 2) {
          navHeight = StyleConstants.WINDOW_NAVGATION_H;
        }else {
          navHeight = this.windowOptions.windowNavHeight;
        }
      }
      if (positionY < navHeight){
        console.info('window放在导航上了,更新为导航底部开始');
        positionY = navHeight;
      }
      let tabbarHeight: number = StyleConstants.WINDOW_BOTTOM_H;
      if (this.windowOptions.windowTabbarHeight){
        if (tabbarHeight > StyleConstants.WINDOW_NAVGATION_H * 2) {
          navHeight = StyleConstants.WINDOW_NAVGATION_H;
        }else {
          tabbarHeight = this.windowOptions.windowTabbarHeight;
        }
      }
      if (vp2px(positionY) + vp2px(window_h) + vp2px(tabbarHeight)>display.getDefaultDisplaySync().height){
        console.error('windowInitPostion 超过屏幕范围 ');
        positionY = display.getDefaultDisplaySync().height - window_h - tabbarHeight;
      }
      let positionX :number = StyleConstants.WINDOW_POSTION.x as number;
      if (this.windowOptions.windowInitPostion){
        if (this.windowOptions.windowInitPostion.x && this.windowOptions.windowInitPostion.x>0) {
          positionX = this.windowOptions.windowInitPostion.x as number
        }
      }
      if (vp2px(positionX)+ vp2px(window_w)>display.getDefaultDisplaySync().width){
        console.error('windowInitPostion 超过屏幕范围 ');
        positionX = display.getDefaultDisplaySync().width
      }
      // 设置悬浮窗位置
      win.moveWindowTo(display.getDefaultDisplaySync().width - vp2px(positionX), vp2px(positionY), (err) => {
        if (err.code) {
          console.error('Failed to move the window. Cause:' + JSON.stringify(err));
          return;
        }
        console.info('Succeeded in moving the window.');
      });
      // 设置悬浮窗大小
      win.resize(window_w, window_h, (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.');
      });
      // 为悬浮窗加载页面内容,这里可以设置在main_pages.json中配置的页面
      win.setUIContent(this.windowOptions.windowShowInContentName, (err: BusinessError) => {
        if (err.code) {
          console.error('Failed to load the content. Cause:' + JSON.stringify(err));
          return;
        }
        win.setWindowBackgroundColor(this.windowOptions.windowBackGroundColor?this.windowOptions.windowBackGroundColor:'#12ffff00')

        console.info('Succeeded in loading the content.');
        // 显示悬浮窗。
        win.showWindow((err: BusinessError) => {
          if (err.code) {
            console.error('Failed to show the window. Cause: ' + JSON.stringify(err));
            return;
          }
          console.info('Succeeded in showing the window.');
        });
      });

    });
  }
  // 自定义销毁悬浮窗方法
  destroyFloatWindow(windowName:string) {
    // 用windowClass调用destroyWindow销毁悬浮窗
    window.findWindow(windowName).destroyWindow((err) => {
      if (err.code) {
        console.error('Failed to destroy the window. Cause: ' + JSON.stringify(err));
        return;
      }
      console.info('Succeeded in destroying the window.');
    });
  }

}
// export  default new FloatWindowUtil(AppStorage.get('windowStage') as window.WindowStage,'1'})

export default class StyleConstants {

  static readonly WINDOW_PAD: number = 5

  static readonly WINDOW_BOTTOM_H: number = 60

  static readonly WINDOW_NAVGATION_H: number = 60

  static readonly WINDOW_SIZE: Size = ({width:40,height:40})

  static readonly WINDOW_POSTION: Position = ({x:40,y:600})

}

使用方法:

@State windowStage: window.WindowStage = AppStorage.get('windowStage') as window.WindowStage;
  private windowName: string = 'floatWindow'
  private floatWindow?: FloatWindowUtil = undefined

  aboutToAppear(): void {
     let floatWindowOptions:FlowWindowOptions = new FlowWindowOptions(this.windowStage,this.windowName,'pages/TotalTimePage',undefined,undefined,undefined,60,60);
     let floatWindow: FloatWindowUtil = new FloatWindowUtil(floatWindowOptions);
     floatWindow.createFloatWindow();
    this.floatWindow = floatWindow;
    AppStorage.setOrCreate('timeFloatWindowName', this.windowName);
  }

参数为undefined的都是默认大小,默认背景色。
效果图如下:
在这里插入图片描述

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luxingxing1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值