鸿蒙技术知多点,技术深入、鸿蒙开发实战分享(一)——下载功能按钮与全局悬浮窗联动实战开发
在移动应用开发中,我们经常会遇到需要持续向用户展示动态数据、提供快速功能导航、支持多任务并行处理等场景。这时候,悬浮窗就成为了一个非常不错和高效的解决方案。接下来要介绍的项目,主要是通过子窗口实现全局悬浮窗效果,通过本题可以让我们初步了解子窗口的创建、定制、销毁。

📋 前言
活动主旨
以 “星光” 为引,为鸿蒙生态聚能!本次征文活动面向全体鸿蒙学习者、开发者及 2024/2025 HarmonyOS 创新赛参赛者,旨在搭建一个技术分享与成长交流的平台 —— 无论是你从入门到精通的鸿蒙学习心得、项目实战中的技术突破,还是鸿蒙相关项目的从 0 到 1 复盘,都能在这里找到共鸣与认可。
关于 HarmonyOS 应用开发者基础认证
通过系统化的课程学习,熟练掌握 DevEco Studio,ArkTS,ArkUI,预览器,模拟器,SDK 等 HarmonyOS 应用开发的关键概念,具备基础的应用开发能力。
🎯 项目介绍
在移动应用开发中,我们经常会遇到需要持续向用户展示动态数据、提供快速功能导航、支持多任务并行处理等场景。这时候,悬浮窗就成为了一个非常不错和高效的解决方案。接下来要介绍的项目,主要是通过子窗口实现全局悬浮窗效果,通过本题可以让我们初步了解子窗口的创建、定制、销毁。
接下来,我们可以通过一个实际案例,带大家深入了解如何在鸿蒙应用中实现全局悬浮窗效果。这个项目是我四月份那会参加广州站的鸿蒙 HDC 活动记录的实战项目,同时也是那天实操环节的项目,因此在这篇文章中给大家分析下这个项目以及实现方法。具体实现的效果如下图。
软件要求:
DevEco Studio 版本:DevEco Studio 5.0.0 Release 及以上。 HarmonyOS SDK 版本:HarmonyOS 5.0.0 Release SDK 及以上。
硬件要求:
华为⼿机、模拟器。(HarmonyOS 系统:HarmonyOS 5.0.0 Release 及以上)
🎯 实现过程
主要代码结构
在 EntryAbility.ets 中获取窗口管理器对象并使用 AppStorage 保存。
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
});
AppStorage.setOrCreate("windowStage",windowStage)
}
窗口管理 WindowUti l文件:负责窗口的创建、窗口样式配置等。如设置窗口长宽分别为 300px;窗口背景颜色为透明。
应用首页 index.ets:这边使用 Tabs() 组件简单实现多页面视图切换,并且在第一个页签内增加测试按钮。
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
private suw = new WindowUtil()
build() {
Tabs() {
TabContent() {
Column() {
Text('首页的内容').fontSize(30)
Button('开始下载任务').onClick(() => {
this.suw.showSubWindow()
})
}
}
.tabBar('首页')
TabContent() {
page1()
}
.tabBar('发现')
TabContent() {
page2()
}
.tabBar('我的')
}
}
}
子窗口页面开发 SubWindow.ets:因为子窗口背景为透明,所以可以通过配置容器或组件样式实现个性化子窗口(该项目通过设置边框圆角实现圆形子窗口,也可以通过 Canvas 实现其形状)。并且通过 gesture 绑定滑动手势,实现窗口跟手效果。
import window from '@ohos.window';
interface Position {
x: number,
y: number
}
@Entry
@Component
struct SubWindow {
@State message: string = '任务准备中';
@State @Watch("moveWindow") windowPosition: Position = { x: 300, y: 300 };
@State progress: number = 0;
private floatWindow: window.Window = window.findWindow("mySubWindow")
private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.All });
build() {
Stack() {
Row() {
Column() {
Text(this.message)
.fontSize(15)
.fontColor(Color.White)
Progress({ value: 0, total: 100, type: ProgressType.Capsule })
.width('80%')
.height(10)
.backgroundColor(Color.Green)
.color(Color.White)
.value(this.progress)
}
.justifyContent(FlexAlign.Center)
.width('100%')
.height('100%')
}
Row() {
Image($r('app.media.close')).width('10vp').height('10vp').onClick(() => {
this.floatWindow.destroyWindow()
})
}
.justifyContent(FlexAlign.End)
.alignItems(VerticalAlign.Top)
.width('100%')
.height('100%')
}
.borderRadius(50)
.backgroundColor(Color.Green)
.gesture(PanGesture(this.panOption).onActionUpdate((event: GestureEvent) => {
this.windowPosition.x += event.offsetX;
this.windowPosition.y += event.offsetY;
})
)
}
aboutToAppear(): void {
setTimeout(() => {
const intervalID = setInterval(() => {
if (this.progress <= 100) {
this.message = '处理中'
this.progress += 1;
} else {
this.message = "任务完成"
clearInterval(intervalID)
}
}, 50)
}, 2000)
}
moveWindow(changedPropertyName: string) {
this.floatWindow.moveWindowTo(this.windowPosition.x, this.windowPosition.y);
}
}
实现效果如下

📝最后
以上就是下载功能按钮与全局悬浮窗联动实战开发的全部内容了,通过本次实战开发,可以深入掌握了应用内全局悬浮窗的实现方案。从窗口管理器的初始化、子窗口的创建与样式配置,到悬浮窗页面的手势交互和进度展示,完整构建了一个可拖拽的圆形悬浮窗组件。
在实际开发中,悬浮窗的使用需要兼顾功能性和用户体验。我们既要注意避免悬浮窗干扰用户正常操作,提供便捷的关闭入口,也要关注性能优化,减少不必要的内存占用。本次实现的悬浮窗支持自由拖拽、进度实时更新和一键关闭,这些特性确保了功能实用性的同时,也体现了对用户体验的细致考量。
更多推荐



所有评论(0)