HarmonyOS NEXT 鸿蒙应用开发 悬浮球--子窗口实现
·
1.准备工作 entryAbility中 暂存主窗口对象
onWindowStageCreate(windowStage: window.WindowStage): void {
//组件间通信 -- 主窗口
AppStorage.setOrCreate('windowStage',windowStage)
// ...
}
2.封装悬浮球的初始化,创建一个系统util文件.ets
export class SubWindow{
static createFloatWindow() {
//拿到主窗口
let windowStage = AppStorage.get("windowStage") as window.WindowStage;
// 在主窗口上创建子窗口 floatWindow
windowStage.createSubWindow("floatWindow", (err, subWin) => {
if (err.code) {
return;
}
// 设置悬浮窗位置
subWin.moveWindowTo(vp2px(255), vp2px(120), (err) => {
if (err.code) {
return;
}
});
// 设置悬浮窗大小
subWin.resize(vp2px(100), vp2px(100), (err) => {
if (err.code) {
return;
}
});
// 为悬浮窗加载页面内容,这里可以设置在main_pages.json中配置的页面(主入口页面路由)
subWin.setUIContent('pages/LevitatedSphere', (err) => {
if (err.code) {
return;
}
//设置悬浮窗背景色
subWin.setWindowBackgroundColor("#00000000")
// 显示悬浮窗。
subWin.showWindow((err) => {
if (err.code) {
return;
}
});
});
});
}
}
3.配置悬浮球的UI结构和逻辑
window.shiftAppWindowFocus()这个方法很重要,需要配置好这个方法,否则主窗口和子窗口展示内容会发生混乱
//LevitatedSphere页面,悬浮球UI页面
windowStage = AppStorage.get("windowStage") as window.WindowStage;//主窗口
async aboutToAppear(){
let subWindowID:number = window.findWindow('floatWindow').getWindowProperties().id
let mainWindowID:number = this.windowStage.getMainWindowSync().getWindowProperties().id
//在同应用内,将窗口焦点从源窗口转移到目标窗口,仅支持应用主窗和子窗的焦点转移
await window.shiftAppWindowFocus(subWindowID,mainWindowID)
//设置子窗口的显示方向,竖屏
this.floatWindow.setPreferredOrientation(window.Orientation.LANDSCAPE)
}
async onPageShow(){
let subWindowID:number = window.findWindow('floatWindow').getWindowProperties().id
let mainWindowID:number = this.windowStage.getMainWindowSync().getWindowProperties().id
await window.shiftAppWindowFocus(subWindowID,mainWindowID)
}
build() {
Column(){
Image($r('app.media.sxi_text')).width(100)
Image($r('app.media.sxi_xf')).width(48)
}
.height(100)
.onClick(()=>{
//悬浮球点击事件,触发emitter
let event: emitter.InnerEvent = {
eventId: 33999
};
emitter.emit(event)
})
}
4.使用悬浮球
//应用的首页
async aboutToAppear() {
//创建悬浮窗
SubWindow.createFloatWindow()
let event: emitter.InnerEvent = {
eventId: 33999
};
emitter.on(event, () => {
const emitterCount = emitter.getListenerCount(33999)
//如果有多个监听,需要销毁监听,避免逻辑重复触发
if (emitterCount !== 1) {
emitter.off(33999)
}
//点击悬浮球后需要执行的逻辑
router.pushUrlByName()
})
}
5.拖动悬浮球
//LevitatedSphere页面
//创建平移手势识别器对象
private panOption:PanGestureOptions = new PanGestureOptions({ direction:PanDirection.All }) //所有方向都可以识别
//悬浮窗的初始位置信息并开启监听
@State @Watch("moveWindow") windowPosition: Position = { x: vp2px(255), y: vp2px(120) };
//找到子窗口
floatWindow :window.Window = window.findWindow('floatWindow') //查找name所对应的窗口。
moveWindow(){
this.floatWindow.moveWindowTo(Number(this.windowPosition.x), Number(this.windowPosition.y));
}
Column(){
Image($r('app.media.sxi_text')).width(100)
Image($r('app.media.sxi_xf')).width(48)
}
.height(100)
.onClick(()=>{
let event: emitter.InnerEvent = {
eventId: 33999
};
emitter.emit(event)
})
.gesture( //给column绑定手势事件
//绑定手势事件
PanGesture(this.panOption)
.onActionStart((event)=>{
//手势绑定成功
})
.onActionUpdate((event)=>{
//发生拖拽时,获取到拖拽信息
this.windowPosition.x += event.offsetX;
this.windowPosition.y += event.offsetY;
})
.onActionEnd(() => {
//手势绑定成功,回调结束时触发
})
)
6.隐藏/显示悬浮窗
minimize()
1.当调用对象为主窗口时,实现最小化功能,可在Dock栏中还原。
2.当调用对象为子窗口时,实现隐藏功能,不可在Dock栏中还原,可以使用showWindow()进行还原。
const floatWindow= window.findWindow('floatWindow')
if (this.currentIndex === 0) {
//首页隐藏悬浮窗
floatWindow.minimize()
}else{
//其他页面显示悬浮球
floatWindow.showWindow()
}
7.特殊场景隐藏悬浮球(如果是组件没有onPageShow的话,可以使用watch监听触发隐藏子窗口)
onPageShow(): void {
//隐藏子窗口
const subWindow = window.findWindow('floatWindow')
subWindow.minimize()
}
onPageHide(): void {
//打开子窗口
const subWindow = window.findWindow('floatWindow')
subWindow.showWindow()
}
更多推荐


所有评论(0)