鸿蒙next 子窗口实现悬浮球功能来了

前言:

最近要写鸿蒙手游sdk 要做悬浮球功能 就找了下资料,然后就写了下这个案例,那么废话不多少我们正式开始。

效果图:

我们可以通过点击显示和隐藏来控制悬浮球的显示和隐藏的情况

具体实现

悬浮球主体的布局和拖动效果

kotlin 复制代码
import { display, inspector, window } from '@kit.ArkUI';
import CommonConstants from '../constants/CommonConstants';
import Logger from '../utils/Logger';
import { WindowPosition } from '../viewmodel/WindowPosition';

@Entry
@Component
struct ResizeWindowPage {
  @State windowStage: window.WindowStage = AppStorage.get('windowStage') as window.WindowStage;
  @State subWindow: window.Window = window.findWindow('ResizeWindowPage');
  @State flag: boolean = true;
  @State windowPosition: WindowPosition = {
    x: CommonConstants.DEFAULT_WINDOW_X,
    y: CommonConstants.DEFAULT_WINDOW_Y
  };
  @StorageLink('screenWidth') screenWidth: number = 0;
  @StorageLink('screenHeight') screenHeight: number = 0;
  listener: inspector.ComponentObserver = inspector.createComponentObserver('COMPONENT_ID');
  private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.All });
  private callback: () => void = () => {
    if (!this.flag) {
      this.subWindow.resize(vp2px(this.screenWidth * CommonConstants.WINDOW_COEFFICIENT),
        vp2px(this.screenHeight * CommonConstants.WINDOW_COEFFICIENT));
    } else {
      this.subWindow.resize(vp2px(CommonConstants.DEFAULT_WINDOW_SIZE),
        vp2px(CommonConstants.DEFAULT_WINDOW_SIZE));
    }
  };

  onPageShow(): void {
    setTimeout(() => {
      try {
        let subWindowID: number = window.findWindow('ResizeWindowPage').getWindowProperties().id;
        let mainWindowID: number = this.windowStage.getMainWindowSync().getWindowProperties().id;
        window.shiftAppWindowFocus(subWindowID, mainWindowID);
      } catch (error) {
        Logger.error('shiftAppWindowFocus failed' + JSON.stringify(error));
      }
    }, CommonConstants.TIME_DELAY)
    this.listener.on('layout', this.callback);
  }

  onPageHide(): void {
    this.listener.off('layout', this.callback);
  }

  /**
   * Move the floating window to the specified position.
   */
  moveWindow() {
    this.subWindow.moveWindowTo(this.windowPosition.x, this.windowPosition.y);
  }

  build() {
    Row() {
      Column() {
        //Image(this.flag ? $r('app.media.ic_public_video') : $r('app.media.ic_public_picture'))
        Image( $r('app.media.hemei_img_float'))
          .height(CommonConstants.FULL_PERCENT)
          .id('COMPONENT_ID')
          .borderRadius(16)
          .onClick(() => {
            //点击显示悬浮窗球
            //this.flag = !this.flag;
          })
      }
    }
    .backgroundColor(Color.Transparent)
    .gesture(
      PanGesture(this.panOption)
        .onActionStart((event: GestureEvent) => {})
        .onActionUpdate((event: GestureEvent) => {
          this.windowPosition.x += event.offsetX;
          this.windowPosition.y += event.offsetY;
          let top = CommonConstants.DEFAULT_HEIGHT;
          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) => {
          if (this.windowPosition.x >= display.getDefaultDisplaySync().width / 2) {
            this.windowPosition.x = display.getDefaultDisplaySync().width -
              this.subWindow.getWindowProperties().windowRect.width;
          } else if (event.offsetX < display.getDefaultDisplaySync().width / 2) {
            this.windowPosition.x = 0;
          }
          let top = CommonConstants.DEFAULT_HEIGHT;
          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);
        })
    )
  }
}

显示

我们使用子窗口设置我们的悬浮球大小和

javascript 复制代码
this.windowStage.createSubWindow('ResizeWindowPage', (err, windowClass) => {
  if (err.code > 0) {
    Logger.error('failed to create subWindow Cause:' + err.message);
    return;
  }
  try {
    windowClass.setUIContent('pages/ResizeWindowPage', () => {
      windowClass.setWindowBackgroundColor('#00000000');
    });
    windowClass.moveWindowTo(CommonConstants.DEFAULT_WINDOW_X, CommonConstants.DEFAULT_WINDOW_Y);
    windowClass.resize(vp2px(CommonConstants.DEFAULT_WINDOW_SIZE), vp2px(CommonConstants.DEFAULT_WINDOW_SIZE));
    windowClass.showWindow();
    windowClass.setWindowLayoutFullScreen(true);
  } catch (err) {
    Logger.error('failed to create subWindow Cause:' + err);
  }
})

隐藏

我们调用 子窗口的 destroyWindow 来隐藏我们的悬浮球即可

javascript 复制代码
if (window.findWindow('ResizeWindowPage').isWindowShowing()) {
  window.findWindow('ResizeWindowPage').destroyWindow();
}
最后总结

华为也是推荐我们使用子窗口来实现悬浮球的的效果,最开始是使用dialog来实现的但是效果不好 ,这种方式不可取,所以我这最后决定使用子窗口来实现。 。今天的文章就讲到这里有兴趣的同学可以继续研究 如果你觉得文章还不错麻烦给我三连 关注点赞和转发 如果了解更多鸿蒙开发的知识 可以关注坚果派公众号 。 谢谢

团队介绍

团队介绍:坚果派由坚果等人创建,团队由12位华为HDE以及若干热爱鸿蒙的开发者和其他领域的三十余位万粉博主运营。专注于分享 HarmonyOS/OpenHarmony,ArkUI-X,元服务,仓颉,团队成员聚集在北京,上海,南京,深圳,广州,宁夏等地,目前已开发鸿蒙 原生应用,三方库60+,欢迎进行课程,项目等合作。

相关推荐
高心星10 小时前
HarmonyOS 5.0应用开发——MVVM模式的应用
harmonyos·mvvm·鸿蒙5.0·备忘录应用
别说我什么都不会10 小时前
【仓颉三方库】工具类—— compress4cj
harmonyos
别说我什么都不会10 小时前
【仓颉三方库】工具类—— uuid4cj
harmonyos
__Benco17 小时前
OpenHarmony - 小型系统内核(LiteOS-A)(十),魔法键使用方法,用户态异常信息说明
人工智能·harmonyos
NapleC1 天前
HarmonyOS:一多能力介绍:一次开发,多端部署
华为·harmonyos
我爱学习_zwj1 天前
【鸿蒙HarmonyOS】深入理解router与Navigation
华为·harmonyos
NapleC1 天前
HarmonyOS:1.7
harmonyos
鸿蒙布道师1 天前
鸿蒙NEXT开发通知工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
鸿蒙布道师1 天前
鸿蒙NEXT开发网络相关工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei