前言:
最近要写鸿蒙手游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+,欢迎进行课程,项目等合作。