鸿蒙-应用内悬浮窗

发布于:2024-12-19 ⋅ 阅读:(11) ⋅ 点赞:(0)

//悬浮窗工具类

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
}