HarmonyOS 应用级的悬浮按钮实现

想实现一个应用级的悬浮按钮,每个页面中都显示可以拖动、跳转其他page时也不会改变按钮的状态和位置。

HarmonyOS
2024-12-24 18:11:45
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
shlp

示例参考如下:

EntryAbility.ets

onWindowStageCreate(windowStage: window.WindowStage): void {
  hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

  windowStage.loadContent('pages/Index', (err) => {
    if (err.code) {
      hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
      return;
    }

    AppStorage.setOrCreate("windowStage", windowStage);
    AppStorage.setOrCreate("mainWindowId", windowStage.getMainWindowSync().getWindowProperties().id);
    hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
  });
}

Index.ets

import { PipWindowComponent } from '../view/PipWindowComponent'
import { ResizeWindowComponent } from '../view/ResizeWindowComponent'
import { MinimizeWindowComponent } from '../view/MinimizeWindowComponent'
import { NavigationWindowComponent } from '../view/NavigationWindowComponent'
import { router, window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit'

@Entry
@Component
struct Index {
  @State windowStage: window.WindowStage = AppStorage.get('windowStage') as window.WindowStage;
  @State flag: boolean = false;
  @Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack();
  private navId: string = 'navId';

  onPageShow(): void {
    AppStorage.setOrCreate('pageInfos', this.pageInfos);
    let windowStage = AppStorage.get('windowStage') as window.WindowStage;
    windowStage.on('windowStageEvent', (data) => {
      if (data === window.WindowStageEventType.PAUSED) {
        this.flag = true;
      } else {
        this.flag = false;
      }
    })
  }

  onBackPress(): boolean | void {
    this.windowStage.getSubWindow().then((data) => {
      data.length = 0;
      if (data.length !== 0) {
        window.getLastWindow(getContext(this), (err: BusinessError, win) => {
          const errCode: number = err.code;
          if (errCode) {
            console.error(`Failed to obtain the main window. Cause code: ${err.code}, message: ${err.message}`);
            return;
          }
          win.destroyWindow();
        })
      } else {
        //关闭应用的操作
        console.log(`关闭应用啦`);
      }
    })
    return true;
  }

  @Builder
  PageMap(name: string) {
    if (name === 'NavigationWindowComponent') {
      NavigationWindowComponent({ navId: this.navId });
    }

  }

  build() {
    Navigation(this.pageInfos) {
      Column() {


        Button('子窗口控制Navigation跳转 ', { stateEffect: true, type: ButtonType.Capsule })
          .width('80%')
          .height(40)
          .margin(20)
          .onClick(() => {
            this.pageInfos.pushPath({ name: 'NavigationWindowComponent' });
          })
          .stateStyles({
            pressed: {
              .backgroundColor(Color.Red);
            },
            normal: {
              .backgroundColor(Color.Blue);
            }
          })

      }
    }.title('')
    .navDestination(this.PageMap)
    // 设置Navigation组件的id属性
    .id(this.navId)
    .foregroundBlurStyle(this.flag ? BlurStyle.Thin : BlurStyle.NONE, {
      colorMode: ThemeColorMode.LIGHT,
      adaptiveColor: AdaptiveColor.DEFAULT
    })
  }
}

NavigationWindowComponent.ets

import { window } from '@kit.ArkUI';

@Component
export struct NavigationWindowComponent {
  @Consume('pageInfos') pageInfos: NavPathStack;
  @State picPath: string = 'app.media.background';
  @State count: number = 1;
  @State windowStage: window.WindowStage = AppStorage.get('windowStage') as window.WindowStage;
  public navId: string = '';

  build() {
    NavDestination() {
      Row() {
        Image($r(this.picPath))
          .height('100%')
          .width('100%')
          .onClick(() => {
            window.findWindow('NavigationControlWindow').showWindow();
          })
      }
      .height('100%')
    }
    .onShown(() => {
      this.windowStage.createSubWindow('NavigationControlWindow', (err, windowClass) => {
        if (err.code > 0) {
          console.error(`failed to create subWindow Cause:${err.message}`);
          return;
        }
        // 设置子窗口加载页
        try {
          windowClass.setUIContent('pages/NavigationControlWindow', () => {
            windowClass.setWindowBackgroundColor('#00000000');
          });
          // 设置子窗口左上角坐标
          windowClass.moveWindowTo(0, 200);
          // 设置子窗口大小
          windowClass.resize(vp2px(75), vp2px(75));
          windowClass.setWindowTouchable(true);
          // 展示子窗口
          windowClass.showWindow();
          // 设置子窗口全屏化布局不避让安全区
          windowClass.setWindowLayoutFullScreen(true);
        } catch (err) {
          console.error(`failed to create subWindow Cause:${err}`)
        }
      })
    })
    .onHidden(() => {
      window.findWindow('NavigationControlWindow').destroyWindow();
    })
    .hideTitleBar(true)
  }
}

WindowUtils.ets

import { window } from '@kit.ArkUI'

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

export function ChangeFocus(windowStage: window.WindowStage, windowName: string) {
  setTimeout(() => {
    // 获取子窗口ID
    let subWindowID: number = window.findWindow(windowName).getWindowProperties().id;
    // 获取主窗口ID
    let mainWindowID: number = windowStage.getMainWindowSync().getWindowProperties().id;
    // 将焦点从子窗口转移到主窗口
    window.shiftAppWindowFocus(subWindowID, mainWindowID);
  }, 500);
}
分享
微博
QQ
微信
回复
2024-12-24 19:25:42
相关问题
HarmonyOS 如何实现底部悬浮按钮
155浏览 • 1回复 待解决
HarmonyOS 悬浮按钮拖动问题
661浏览 • 1回复 待解决
HarmonyOS APP内悬浮按钮开发方案
395浏览 • 1回复 待解决
音乐播放悬浮按钮该如何布局?
1069浏览 • 1回复 待解决
基于子窗口实现应用悬浮
857浏览 • 1回复 待解决
HarmonyOS 应用全局弹框
553浏览 • 1回复 待解决
HarmonyOS 关于应用字体调整
458浏览 • 1回复 待解决
HarmonyOS 如何实现可以拖动悬浮
342浏览 • 1回复 待解决
HarmonyOS 获取应用access token失败
580浏览 • 1回复 待解决
关于华为应用AT一些问题
12250浏览 • 3回复 待解决