鸿蒙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+,欢迎进行课程,项目等合作。

相关推荐
zhanshuo1 小时前
在鸿蒙里优雅地处理网络错误:从 Demo 到实战案例
harmonyos
zhanshuo1 小时前
在鸿蒙中实现深色/浅色模式切换:从原理到可运行 Demo
harmonyos
whysqwhw6 小时前
鸿蒙分布式投屏
harmonyos
whysqwhw7 小时前
鸿蒙AVSession Kit
harmonyos
whysqwhw9 小时前
鸿蒙各种生命周期
harmonyos
whysqwhw10 小时前
鸿蒙音频编码
harmonyos
whysqwhw10 小时前
鸿蒙音频解码
harmonyos
whysqwhw10 小时前
鸿蒙视频解码
harmonyos
whysqwhw10 小时前
鸿蒙视频编码
harmonyos
ajassi200010 小时前
开源 Arkts 鸿蒙应用 开发(十八)通讯--Ble低功耗蓝牙服务器
华为·开源·harmonyos