
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@Componentstruct 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';interfacePosition{ x: number, y: number}@Entry@Componentstruct 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); }}
实现效果如下


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