如何实现 app 内置全局悬浮球功能?

app 内有在主 window 上面的悬浮球, 支持手指按住移动位置, 点击会弹出功能菜单。 不需要退到后台还显示,仅仅在 app 内展示,类似与快捷功能入口

尝试方案:

1. 使用全屏透明子 window ,上面只有悬浮球控件, 但是下层主 window 所有事件不会触发。如关闭子 window 交互事件, 下层 window 事件可以触发, 但是悬浮球又拖动不了

2. 尝试过单页面创建悬浮球, 但是每个页面都要创建一个, 内存消耗较大

HarmonyOS
2024-04-29 16:56:48
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
bysc111

窗管级悬浮窗请参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-window-0000001820880785#ZH-CN_TOPIC_0000001820880785__windowtype7

参考如下Demo:

import { window } from '@kit.ArkUI'; 
 
@Entry 
@Component 
struct Page3 { 
  @State message: string = 'Hello World'; 
 
  build() { 
    Row() { 
      Column() { 
        Text(this.message) 
          .fontSize(50) 
          .fontWeight(FontWeight.Bold) 
          .onClick(() => { 
 
            let windowStage = AppStorage.get("windowStage") as window.WindowStage; 
            windowStage.createSubWindow("test", (err, win) => { 
              win.setUIContent("pages/Page2"); 
              win.resize(500, 500); 
              win.moveWindowTo(200, 200); 
              win.showWindow(); 
            }) 
          }) 
      } 
      .width('100%') 
    } 
    .height('100%') 
    .backgroundColor(Color.Pink) 
  } 
} 
//FloatContent.ets 
import window from '@ohos.window'; 
 
interface Position { 
  x: number, 
  y: number 
} 
@Entry 
@Component 
struct FloatContent { 
  @State message: string = 'float window' 
  private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.All }); 
  // 创建位置变量,并使用@Watch监听,变量发生变化调用moveWindow方法移动窗口 
  @State @Watch("moveWindow") windowPosition: Position = { x: 0, y: 0 }; 
  floatWindow: window.Window = window.findWindow("floatWindow") 
  // 通过悬浮窗名称“floatWindow”获取到创建的悬浮窗 
  aboutToAppear() { 
    this.floatWindow = window.findWindow("floatWindow") 
    this.floatWindow.setPreferredOrientation(window.Orientation.LANDSCAPE) 
  } 
  // 将悬浮窗移动到指定位置 
  moveWindow() { 
    this.floatWindow.moveWindowTo(this.windowPosition.x, this.windowPosition.y); 
  } 
 
  build() { 
    Row() { 
      Column() { 
        Text(this.message) 
          .fontSize(30) 
          .fontColor(Color.White) 
          .fontWeight(FontWeight.Bold) 
      } 
      .width('100%') 
    } 
    .borderRadius(500) 
    .height('100%') 
    .gesture( 
      // 绑定PanGesture事件,监听拖拽动作 
      PanGesture(this.panOption) 
        .onActionStart((event: GestureEvent) => { 
          console.info('Pan start'); 
        }) 
          // 发生拖拽时,获取到触摸点的位置,并将位置信息传递给windowPosition 
        .onActionUpdate((event: GestureEvent) => { 
          this.windowPosition.x += event.offsetX; 
          this.windowPosition.y += event.offsetY; 
        }) 
        .onActionEnd(() => { 
          console.info('Pan end'); 
        }) 
    ) 
    .border({ 
      style: BorderStyle.Dotted 
    }) 
    .backgroundColor("#E8A49C") 
  } 
} 
//FloatWindow.ets 
// 引入window类 
import window from '@ohos.window'; 
import { BusinessError } from '@ohos.base'; 
import router from '@ohos.router'; 
 
@Entry 
@Component 
struct FloatWindow { 
  // 定义windowClass变量,用来接收创建的悬浮窗 
  // 自定义创建悬浮窗方法 
  createFloatWindow() { 
    // 窗口类型设置为window.WindowType.TYPE_FLOAT 
    let windowStage = AppStorage.get("windowStage") as window.WindowStage; 
 
    // let config:window.Configuration = {name: "floatWindow", windowType: window.WindowType.TYPE_FLOAT, ctx: getContext(this)}; 
    // 创建悬浮窗 
    windowStage.createSubWindow("floatWindow", (err, win) => { 
 
      if (err.code) { 
        console.error('Failed to create the floatWindow. Cause: ' + JSON.stringify(err)); 
        return; 
      } 
      console.info('Succeeded in creating the floatWindow. Data: ' + JSON.stringify(win)); 
 
      // 设置悬浮窗位置 
      win.moveWindowTo(300, 300, (err) => { 
        if (err.code) { 
          console.error('Failed to move the window. Cause:' + JSON.stringify(err)); 
          return; 
        } 
        console.info('Succeeded in moving the window.'); 
      }); 
      // 设置悬浮窗大小 
      win.resize(500, 500, (err) => { 
        if (err.code) { 
          console.error('Failed to change the window size. Cause:' + JSON.stringify(err)); 
          return; 
        } 
        console.info('Succeeded in changing the window size.'); 
      }); 
      // 为悬浮窗加载页面内容,这里可以设置在main_pages.json中配置的页面 
      win.setUIContent("pages/FloatContent", (err: BusinessError) => { 
        if (err.code) { 
          console.error('Failed to load the content. Cause:' + JSON.stringify(err)); 
          return; 
        } 
        win.setWindowBackgroundColor("#00000000") 
        console.info('Succeeded in loading the content.'); 
        // 显示悬浮窗。 
        win.showWindow((err: BusinessError) => { 
          if (err.code) { 
            console.error('Failed to show the window. Cause: ' + JSON.stringify(err)); 
            return; 
          } 
          console.info('Succeeded in showing the window.'); 
        }); 
      }); 
 
    }); 
  } 
  // 自定义销毁悬浮窗方法 
  destroyFloatWindow() { 
    // 用windowClass调用destroyWindow销毁悬浮窗 
    window.findWindow("floatWindow").destroyWindow((err) => { 
      if (err.code) { 
        console.error('Failed to destroy the window. Cause: ' + JSON.stringify(err)); 
        return; 
      } 
      console.info('Succeeded in destroying the window.'); 
    }); 
  } 
 
  build() { 
    Row() { 
      Column() { 
        TextInput() 
        Button('创建悬浮窗') 
          .backgroundColor('#F9C449') 
          .onClick(() => { 
            // 点击按钮调用创建悬浮窗方法 
            this.createFloatWindow(); 
          }) 
        Button('销毁悬浮窗') 
          .margin({ top: 20 }) 
          .backgroundColor('#F9C449') 
          .onClick(() => { 
            // 点击按钮调用销毁悬浮窗方法 
            this.destroyFloatWindow(); 
          }) 
 
        Button('跳转下一页') 
          .margin({ top: 20 }) 
          .backgroundColor('#F9C449') 
          .onClick(() => { 
            // 点击按钮调用销毁悬浮窗方法 
            router.pushUrl({ 
              url: 'pages/Index' 
            }) 
          }) 
      } 
      .width('100%') 
    } 
    .height('100%') 
  } 
}
分享
微博
QQ
微信
回复
2024-04-30 10:45:13
相关问题
悬浮能调用锁屏功能吗?
114浏览 • 1回复 待解决
如何实现悬浮窗桌面穿透
392浏览 • 1回复 待解决
如何实现全局浮窗效果
766浏览 • 1回复 待解决
使用悬浮窗和端内want唤醒APP
495浏览 • 1回复 待解决
鸿蒙如何实现分享功能
16335浏览 • 2回复 待解决
定时提醒功能如何实现?
3633浏览 • 1回复 待解决
Grid如何实现拖拽功能
1192浏览 • 1回复 待解决
如何实现Fraction懒加载功能
6257浏览 • 1回复 待解决
如何实现文本展开收起功能
261浏览 • 1回复 待解决
如何实现类似插槽的功能
790浏览 • 1回复 待解决
基于子窗口实现应用内悬浮
201浏览 • 1回复 待解决
grid如何怎么实现拖拽功能
403浏览 • 1回复 待解决
如何全局存储WebController
444浏览 • 1回复 待解决
如何全局实现一个自定义dialog弹窗
1328浏览 • 1回复 待解决
音乐播放悬浮按钮该如何布局?
391浏览 • 1回复 待解决
如何实现类似.9 图的功能
519浏览 • 1回复 待解决
JS如何实现手机扫码功能
1909浏览 • 1回复 待解决
camera_lite预览功能如何实现
1198浏览 • 0回复 待解决
如何实现媒体会话交互功能
291浏览 • 1回复 待解决
如何实现双路预览+录制功能
518浏览 • 1回复 待解决
【JS】如何实现左滑删除功能
2211浏览 • 1回复 待解决
求大佬告知如何实现复制功能
724浏览 • 1回复 待解决