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

相关推荐
Hi-Dison7 分钟前
Open HarmonyOS 5.0 分布式软总线子系统 (DSoftBus) 详细设计与运行分析报告
分布式·华为·harmonyos
李游Leo3 小时前
HarmonyOS:ArkTS Path 组件自学指南
harmonyos
zhousg3 小时前
HarmonyOS NEXT AI基础语音服务-文章播报
harmonyos
zhousg3 小时前
HarmonyOS NEXT AI基础视觉服务-文字识别
harmonyos
小藤神3 小时前
鸿蒙ArkTS 视频相关 视频播放、直播视频、XComponent和typeNode多方案实现画中画功能开发
华为·harmonyos·arkts
中雨20255 小时前
HarmonyOS NEXT函数和自定义构建函数
harmonyos
博睿谷IT99_5 小时前
华为HCIE鸿蒙应用开发认证靠谱吗?
华为认证·hcie·harmonyos·鸿蒙·鸿蒙系统
二流小码农6 小时前
鸿蒙开发:Canvas绘制之画笔对象Brush
android·ios·harmonyos
二流小码农6 小时前
鸿蒙开发:事件订阅EventHub
android·ios·harmonyos
失落的多巴胺7 小时前
嵌入式项目:基于QT与海思HI3861开发板设计的鸿蒙智能车
开发语言·嵌入式硬件·qt·学习·harmonyos