文档管理中心

PC上如何实现全局悬浮窗效果

问题现象

在PC上如何实现全局悬浮窗的效果?

背景知识

解决方案

实现悬浮窗有设置全局悬浮窗和多开Ability窗口这两种方案。

方法一:可以参考官方文档全局悬浮窗开发指导,需要申请受限权限ohos.permission.SYSTEM_FLOAT_WINDOW

方法二:使用多开Ability的方案,拉起新的Ability窗口,悬浮窗口需要满足如下特点:无窗口标签栏;无最大化、最小化、关闭窗口按钮;悬浮窗口保持全局置顶效果;主窗口最小化之后,悬浮窗口不跟随最小化;悬浮窗口不响应拖拽到屏幕边缘最大化、分屏等效果。

  1. 新建独立窗口的代码src/main/ets/pages/pageTwo.ets并在配置文件src/main/resources/base/profile/main_pages.json中新增路径:
    收起
    自动换行
    深色代码主题
    复制
    1. @Entry
    2. @Component
    3. struct PageTwo {
    4. build() {
    5. Column() {
    6. Text('Float Window')
    7. .width('100%')
    8. .height('100%')
    9. .fontSize(30)
    10. .textAlign(TextAlign.Center)
    11. }
    12. }
    13. }
    收起
    自动换行
    深色代码主题
    复制
    1. {
    2. "src": [
    3. "pages/Index",
    4. "pages/pageTwo"
    5. ]
    6. }
  2. 在src/main/module.json5中配置窗口全局置顶权限:
    收起
    自动换行
    深色代码主题
    复制
    1. "requestPermissions": [
    2. {
    3. "name": "ohos.permission.WINDOW_TOPMOST"
    4. }
    5. ],
  3. 新增文件src/main/ets/entryability/FloatWindowAbility.ets,声明FloatWindowAbility类,继承自UIAbility,在接口onWindowStageCreateloadContent之后获取主窗口对象。对该窗口设置标题栏不可见,最大化、最小化、关闭按钮不可见,设置窗口全局置顶等属性:
    收起
    自动换行
    深色代码主题
    复制
    1. export default class FloatWindowAbility extends UIAbility {
    2. private async resizeWindow(win: window.Window, width: number, height: number): Promise<void> {
    3. try {
    4. await win.resize(width, height);
    5. console.info('Succeeded in resizing window.');
    6. } catch (err) {
    7. console.error(`resize window failed: <${err.code}>${err.message}`);
    8. }
    9. }
    10. private setDecorVisible(win: window.Window, isVisible: boolean) {
    11. try {
    12. win.setWindowDecorVisible(isVisible);
    13. console.info('set window decor visible success.');
    14. } catch (err) {
    15. console.error(`set window decor visible failed: <${err.code}>${err.message}`);
    16. }
    17. }
    18. private setTitleButtonVisible(win: window.Window, isMaxVisible: boolean,
    19. isMinVisible: boolean, isCloseVisible?: boolean) {
    20. try {
    21. win.setWindowTitleButtonVisible(isMaxVisible, isMinVisible, isCloseVisible);
    22. console.info('set window title button visible success.');
    23. } catch (err) {
    24. console.error(`set window title button visible failed: <${err.code}>${err.message}`);
    25. }
    26. }
    27. private async setTopmost(win: window.Window, isWindowTopmost: boolean): Promise<void> {
    28. try {
    29. await win.setWindowTopmost(isWindowTopmost);
    30. console.info('set window topmost success.');
    31. } catch (err) {
    32. console.error(`set window topmost failed: <${err.code}>${err.message}`);
    33. }
    34. }
    35. onWindowStageCreate(windowStage: window.WindowStage): void {
    36. // 加载主窗口对应的页面。
    37. windowStage.loadContent('pages/pageTwo', () => {
    38. let mainWindow: window.Window | undefined = undefined;
    39. // 获取应用主窗口。
    40. windowStage.getMainWindow().then(async (data: window.Window) => {
    41. if (!data) {
    42. return;
    43. }
    44. mainWindow = data;
    45. // 设置窗口大小
    46. await this.resizeWindow(mainWindow, 200, 100);
    47. // 设置窗口标题可见
    48. this.setDecorVisible(mainWindow, false);
    49. // 设置窗口最大化、最小化、关闭按钮可见
    50. this.setTitleButtonVisible(mainWindow, false, false, false);
    51. // 设置窗口置顶
    52. await this.setTopmost(mainWindow, true);
    53. }).catch((err: BusinessError) => {
    54. if (err.code) {
    55. console.error(`Failed to obtain the main window. Cause code: ${err.code}, message: ${err.message}`);
    56. }
    57. });
    58. });
    59. }
    60. }
  4. 在应用配置文件src/main/module.json5的abilities属性中,新增FloatWindowAbility配置项以及supportWindowMode属性为floating:
    收起
    自动换行
    深色代码主题
    复制
    1. {
    2. "name": "FloatWindowAbility",
    3. "srcEntry": "./ets/entryability/FloatWindowAbility.ets",
    4. "description": "$string:EntryAbility_desc",
    5. "icon": "$media:layered_image",
    6. "label": "$string:EntryAbility_label",
    7. "supportWindowMode": ["floating"],
    8. "startWindowIcon": "$media:startIcon",
    9. "startWindowBackground": "$color:start_window_background",
    10. "exported": true,
    11. "skills": [
    12. {
    13. "entities": [
    14. "entity.system.home"
    15. ],
    16. "actions": [
    17. "ohos.want.action.home"
    18. ]
    19. }
    20. ]
    21. }
  5. 在主界面配置拉起FloatWindowAbility窗口按钮:
    收起
    自动换行
    深色代码主题
    复制
    1. import { common, Want } from '@kit.AbilityKit';
    2. import { BusinessError } from '@kit.BasicServicesKit';
    3. @Entry
    4. @Component
    5. struct Index {
    6. private abilityContext: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
    7. build() {
    8. Column({ space: 20 }) {
    9. Button('拉起悬浮窗')
    10. .onClick(() => {
    11. let want: Want = {
    12. // 此处需要根据实际包名进行更改
    13. bundleName: 'com.example.myapplication',
    14. abilityName: 'FloatWindowAbility',
    15. moduleName: 'entry',
    16. };
    17. this.abilityContext?.startAbility(want)
    18. .then(() => {
    19. console.info('start ability success');
    20. }).catch((error: BusinessError) => {
    21. console.error(`start ability failed, code: ${error.code}, message: ${error.message}`);
    22. });
    23. })
    24. }
    25. .width('100%')
    26. .height('100%')
    27. .justifyContent(FlexAlign.Center)
    28. }
    29. }
在 FAQ 中进行搜索
请输入您想要搜索的关键词