鸿蒙-应用内悬浮窗

news2024/12/20 2:13:47

//悬浮窗工具类

import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
import { Logger } from '@mbbase/common-ui';
import * as FloatedWindowPage from './FloatedWindowPage'; // 导入命名路由页面

const TAG = '[FloatedWindowUtils]';

export interface FloatedWindowParams {
  width: number;
  height: number;
  x: number;
  y: number;
  backgroundColor?: string;
}

export class FloatedWindowUtils {
  public static showSubWindow(windowStage: window.WindowStage | undefined,
    subWindowParams: FloatedWindowParams) {
    if (!windowStage) {
      Logger.error(TAG, `windowStage is undefined.`);
      return;
    }

    windowStage.createSubWindow(FloatedWindowPage.subWindowName, (err, subWindow) => {
      try {
        subWindow.loadContentByName(FloatedWindowPage.entryName, (err: BusinessError) => {
          if (err.code) {
            Logger.error(TAG, `Failed to load the content. Cause: ${err.message}.`);
            return;
          }
          Logger.info('Succeeded in loading the content.');
          subWindow.setWindowBackgroundColor(subWindowParams.backgroundColor ?? '#00ffffff');
          subWindow.moveWindowTo(subWindowParams.x, subWindowParams.y);
          subWindow.resize(subWindowParams.width, subWindowParams.height)
          subWindow.setWindowTouchable(true);
          subWindow.showWindow();
          // subWindow.setWindowBackgroundColor(Color.Transparent.toString());
          subWindow.setWindowLayoutFullScreen(true);
        })
      } catch (err) {
        Logger.error('failed to create subWindow Cause:' + err);
      }
    })
  }

  public static async getFloatedWindow(): Promise<window.Window | undefined> {
    let windowStage = await AppStorage.get<window.WindowStage>('windowStage');
    if (!windowStage) {
      return undefined;
    }

    let subList = await windowStage.getSubWindow()


    for (let i = 0; i < subList.length; i++) {
      let aa: window.WindowProperties = subList[i].getWindowProperties()
      // if (aa.name == 'FloatedWindow') {
      return subList[i];
      // }
    }
    return undefined;
  }


  public static async destroySubWindow() {
    try {
      let subWindow: window.Window = await window.findWindow(FloatedWindowPage.subWindowName)
      if (!subWindow) {
        Logger.info('subWindow is undefined.');
        return;
      }
      subWindow.destroyWindow((err: BusinessError) => {
        if (err.code) {
          Logger.error(TAG, `Failed to destroy the window. Cause: ${err.message}.`);
          return;
        }
        AppStorage.set<window.Window>('subWindow', undefined);
        Logger.info('Succeeded in destroying the window.');
      });
    } catch (err) {
      Logger.error('Find subWindow failed. Cause:' + err);
    }
  }

  public static async moveSubWindow(x: number, y: number) {
    try {
      let subWindow: window.Window = window.findWindow(FloatedWindowPage.subWindowName)
      if (!subWindow) {
        Logger.info('subWindow is undefined.');
        return;
      }

      subWindow.moveWindowTo(x, y, (err: BusinessError) => {
        if (err.code) {
          Logger.error(TAG, `Failed to move the window. Cause: ${err.message}.`);
          return;
        }
        Logger.info('Succeeded in moving the window.', x, y);
      });
    } catch (err) {
      Logger.error('Find subWindow failed. Cause:' + err);
    }
  }

  public static async resizeSubWindow(width: number, height: number) {
    try {
      let subWindow: window.Window = window.findWindow(FloatedWindowPage.subWindowName)
      if (!subWindow) {
        Logger.info('subWindow is undefined.');
        return;
      }
      subWindow.resize(vp2px(width), vp2px(height), (err: BusinessError) => {
        if (err.code) {
          Logger.error(TAG, `Failed to change the window size. Cause: ${err.message}.`);
          return;
        }
        Logger.info('Succeeded in changing the window size.');
      })
    } catch (err) {
      Logger.error('Find subWindow failed. Cause:' + err);
    }
  }
}

 

//悬浮窗页面

import { display, window } from '@kit.ArkUI'
import { MBRouter } from '@mbbase/router'

export const entryName: string = 'FloatedWindowName';

export const subWindowName: string = 'FloatedWindow';

@Entry({ routeName: entryName })
@Component
export struct FloatedWindowPage {
  @State subWindow: window.Window = window.findWindow(subWindowName)
  @State @Watch('moveWindow') windowPosition: WindowPosition = {
    x: 40,
    y: 800
  }

  moveWindow() {
    this.subWindow.moveWindowTo(this.windowPosition.x, this.windowPosition.y);
  }

  build() {
    Row() {
      Text('悬浮窗')
        .fontColor(Color.Red)
        .fontWeight(800)
        .onClick(() => {
          // MBRouter.push({ url: "ymm://test/debug" })
        })
    }.width('100%').height('100%')
    .gesture(
      PanGesture()
        .onActionStart(() => {
        })
        .onActionUpdate((event: GestureEvent) => {
          this.windowPosition.x += event.offsetX;
          this.windowPosition.y += event.offsetY;
          let top = 80;
          let bottom =
            display.getDefaultDisplaySync().height - this.subWindow.getWindowProperties().windowRect.height
              - top;
          if (this.windowPosition.y < top) {
            this.windowPosition.y = top;
          } else if (this.windowPosition.y > bottom) {
            this.windowPosition.y = bottom;
          }
          this.subWindow.moveWindowTo(this.windowPosition.x, this.windowPosition.y);
        })
        .onActionEnd((event: GestureEvent) => {
          let rect = this.subWindow.getWindowProperties().windowRect;

          if (this.windowPosition.x + rect.width / 2 >= display.getDefaultDisplaySync().width / 2) {
            this.windowPosition.x = display.getDefaultDisplaySync().width - rect.width;
          } else if (event.offsetX < display.getDefaultDisplaySync().width / 2) {
            this.windowPosition.x = 0;
          }
          let top = 80;
          let bottom =
            display.getDefaultDisplaySync().height - rect.height
              - top;
          if (this.windowPosition.y < top) {
            this.windowPosition.y = top;
          } else if (this.windowPosition.y > bottom) {
            this.windowPosition.y = bottom;
          }
          this.subWindow.moveWindowTo(this.windowPosition.x, this.windowPosition.y);
        })
    )
  }
}

export interface WindowPosition {
  x: number,
  y: number
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2262458.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

决策树的生成与剪枝

决策树的生成与剪枝 决策树的生成生成决策树的过程决策树的生成算法 决策树的剪枝决策树的损失函数决策树的剪枝算法 代码 决策树的生成 生成决策树的过程 为了方便分析描述&#xff0c;我们对上节课中的训练样本进行编号&#xff0c;每个样本加一个ID值&#xff0c;如图所示…

51c嵌入式~单片机~合集2

我自己的原文哦~ https://blog.51cto.com/whaosoft/12362395 一、不同的电平信号的MCU怎么通信&#xff1f; 下面这个“电平转换”电路&#xff0c;理解后令人心情愉快。电路设计其实也可以很有趣。 先说一说这个电路的用途&#xff1a;当两个MCU在不同的工作电压下工作&a…

Kerberos实验

kdc&#xff1a;192.168.72.163 客户端&#xff08;机器账户win10&#xff09;&#xff1a;192.168.72.159 用户&#xff1a;administrator 抓包&#xff1a;开机登录win10&#xff0c;使用administrator域用户凭据登录。 生成 Kerberos 解密文件 抓取 krbtgt 用户和 win1…

AI一键分析小红书对标账号‼️

宝子们&#xff0c;AI小助手近期发现了一款宝藏AI工具&#xff0c;拥有对标账号AI分析功能&#xff0c;只需10秒就能全面掌握对标账号的运营情况&#xff0c;并且可以根据分析结果提供创作方向和灵感&#xff0c;轻松助力1:1复刻起号&#xff01; 功能亮点&#xff1a; &…

大腾智能CAD:国产云原生三维设计新选择

在快速发展的工业设计领域&#xff0c;CAD软件已成为不可或缺的核心工具。它通过强大的建模、分析、优化等功能&#xff0c;不仅显著提升了设计效率与精度&#xff0c;还促进了设计思维的创新与拓展&#xff0c;为产品从概念构想到实体制造的全过程提供了强有力的技术支持。然而…

VMware虚拟机 Ubuntu没有共享文件夹的问题

在虚拟机的Ubuntu系统中&#xff0c;共享文件目录存放在 mnt/hgfs 下面&#xff0c;但是我安装完系统并添加共享文件后发现&#xff0c;在mnt下连/hgfs目录都没有。 注意&#xff1a;使用共享文件目录需要已安装VMtools工具。 添加共享文件目录 一&#xff1a;在超级用户下 可…

OpenGL ES 01 渲染一个四边形

项目架构 着色器封装 vertex #version 300 es // 接收顶点数据 layout (location 0) in vec3 aPos; // 位置变量的属性位置值为0 layout (location 1) in vec4 aColors; // 位置变量的属性位置值为1 out vec4 vertexColor; // 为片段着色器指定一个颜色输出void main() {gl…

leetcode二叉搜索树部分笔记

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 二叉搜索树 1. 二叉搜索树的最小绝对差2. 二叉搜索树中第 K 小的元素3. 验证二叉搜索树 1. 二叉搜索树的最小绝对差 给你一个二叉搜索树的根节点 root &#xff0c;返回 树中…

推送本地仓库到远程git仓库

目录 推送本地仓库到远程git仓库1.1修改本地仓库用户名1.2 push 命令1.3远程分支查看 推送本地仓库到远程git仓库 删除之前的仓库中的所有内容&#xff0c;从新建库&#xff0c;同时创建一个 A.txt 文件 清空原有的远程仓库内容&#xff0c;重新创建一个新的仓库&#xff0c;…

暂停一下,给Next.js项目配置一下ESLint(Next+tailwind项目)

前提 之前开自己的GitHub项目&#xff0c;想着不是团队项目&#xff0c;偷懒没有配置eslint&#xff0c;后面发现还是不行。eslint的存在可以帮助我们规范代码格式&#xff0c;同时 ctrl s保存立即调整代码格式是真的很爽。 除此之外&#xff0c;团队使用eslint也是好处颇多…

基于微信小程序的小区疫情防控ssm+论文源码调试讲解

第2章 程序开发技术 2.1 Mysql数据库 为了更容易理解Mysql数据库&#xff0c;接下来就对其具备的主要特征进行描述。 &#xff08;1&#xff09;首选Mysql数据库也是为了节省开发资金&#xff0c;因为网络上对Mysql的源码都已进行了公开展示&#xff0c;开发者根据程序开发需…

Win11安装安卓子系统WSA

文章目录 简介一、启用Hyper-V二、安装WSA三、安装APKAPK商店参考文献 简介 WSA&#xff1a;Windows Subsystem For Android 一、启用Hyper-V 控制面板 → 程序和功能 → 启用或关闭 Windows 功能 → 勾选 Hyper-V 二、安装WSA 进入 Microsoft Store&#xff0c;下拉框改为 …

[面试题]--索引用了什么数据结构?有什么特点?

答&#xff1a;使用了B树&#xff1a; 时间复杂度&#xff1a;O(logN),可以有效控制树高 B树特点&#xff1a; 1.叶子节点之间有相互链接的作用&#xff0c;会指向下一个相近的兄弟节点。 MySQL在组织叶子节点使用的是双向链表 2.非叶子节点的值都保存在叶子节点当中 MySQL非叶…

Element plus 下拉框组件选中一个选项后显示的是 value 而不是 label

最近刚进行 Vue3 Element plus 项目实践&#xff0c;在进行表单二次封装的时候&#xff0c;表单元素 select 下拉框组件选中一个选项后显示的是 value 而不是 label&#xff0c;下面上代码&#xff1a; 原来的写法&#xff1a; <el-selectv-if"v.type select"…

bean创建源码

去字节面试&#xff0c;直接让人出门左拐&#xff1a;Bean 生命周期都不知道&#xff01; spring启动创建bean流程 下面就接上了 bean生命周期 doGetBean Object sharedInstance this.getSingleton(beanName); sharedInstance this.getSingleton(beanName, new ObjectF…

【C++】- 掌握STL List类:带你探索双向链表的魅力

文章目录 前言&#xff1a;一.list的介绍及使用1. list的介绍2. list的使用2.1 list的构造2.2 list iterator的使用2.3 list capacity2.4 list element access2.5 list modifiers2.6 list的迭代器失效 二.list的模拟实现1. list的节点2. list的成员变量3.list迭代器相关问题3.1…

泷羽sec学习打卡-brupsuite8伪造IP和爬虫审计

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都 与本人无关,切莫逾越法律红线,否则后果自负 关于brupsuite的那些事儿-Brup-FaskIP 伪造IP配置环境brupsuite导入配置1、扩展中先配置python环境2、安…

挑战一个月基本掌握C++(第五天)了解运算符,循环,判断

一 运算符 运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C 内置了丰富的运算符&#xff0c;并提供了以下类型的运算符&#xff1a; 算术运算符关系运算符逻辑运算符位运算符赋值运算符杂项运算符 1.1 算术运算符 假设变量 A 的值为 10&#xff0c;变量 B 的值为…

JAVA没有搞头了吗?

前言 今年的Java程序员群体似乎承受着前所未有的焦虑。投递简历无人问津&#xff0c;难得的面试机会也难以把握&#xff0c;即便成功入职&#xff0c;也往往难以长久。于是&#xff0c;不少程序员感叹&#xff1a;互联网的寒冬似乎又一次卷土重来&#xff0c;环境如此恶劣&…