HarmonyOS 鸿蒙Next:实现一个简单的app内部的悬浮窗
HarmonyOS 鸿蒙Next:实现一个简单的app内部的悬浮窗
简单的能点击能拖动的component 但是长按不能出现拖拽的现象
2 回复
参考demo:
1、onWindowStageCreate中记录windowStage
onWindowStageCreate(windowStage: window.WindowStage): void {
// 记录
AppStorage.setOrCreate("windowStage",windowStage)
}
2、FloatWindow页面
//FloatWindow.ets
// 引入window类
import window from '[@ohos](/user/ohos).window';
import { BusinessError } from '[@ohos](/user/ohos).base';
import router from '[@ohos](/user/ohos).router';
[@Entry](/user/Entry)
[@Component](/user/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%')
}
}
3、FloatContent页面
//FloatContent.ets
import window from '[@ohos](/user/ohos).window';
interface Position {
x: number,
y: number
}
[@Entry](/user/Entry)
[@Component](/user/Component)
struct FloatContent {
[@State](/user/State) message: string = 'float window'
private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.All });
// 创建位置变量,并使用[@Watch](/user/Watch)监听,变量发生变化调用moveWindow方法移动窗口
[@State](/user/State) [@Watch](/user/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")
}
}
在HarmonyOS(鸿蒙)系统中实现一个简单的App内部悬浮窗功能,可以通过使用悬浮窗服务(FloatingWindowService)来完成。以下是一个简要的实现步骤概述:
-
权限声明:首先,在
config.json
文件中声明悬浮窗权限,确保应用有权限创建悬浮窗。 -
创建悬浮窗布局:在
resources/layout
目录下创建一个XML布局文件,定义悬浮窗的UI。 -
启动悬浮窗服务:在App的适当位置(如某个Activity中),通过
Ability
或Context
启动悬浮窗服务。使用Intent
指定悬浮窗的布局和必要的参数。 -
处理悬浮窗逻辑:在悬浮窗服务的代码中,处理悬浮窗的显示、隐藏、移动等逻辑。可以通过
WindowManager
来管理悬浮窗的视图。 -
与主App交互:如果需要,可以通过广播、AIDL等方式实现悬浮窗与主App之间的数据交互。
请注意,实现细节可能因HarmonyOS版本和具体需求而有所不同。确保遵循最新的HarmonyOS开发文档和最佳实践。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html