鸿蒙OS中实现悬浮窗功能的详细部署过程

举报
Y-StarryDreamer 发表于 2024/07/25 11:28:41 2024/07/25
【摘要】 项目介绍与发展鸿蒙OS(HarmonyOS)作为华为推出的全场景分布式操作系统,旨在为各种智能设备提供统一的系统平台。悬浮窗(Floating Window)是一种常见的UI组件,允许应用在其他应用之上显示内容。它通常用于实现诸如聊天气泡、工具栏、悬浮按钮等功能。在鸿蒙OS中,开发悬浮窗功能需要理解系统权限、窗口管理和UI绘制等方面的知识。本文将详细介绍如何在鸿蒙OS中实现悬浮窗功能,包含项...


项目介绍与发展

鸿蒙OS(HarmonyOS)作为华为推出的全场景分布式操作系统,旨在为各种智能设备提供统一的系统平台。悬浮窗(Floating Window)是一种常见的UI组件,允许应用在其他应用之上显示内容。它通常用于实现诸如聊天气泡、工具栏、悬浮按钮等功能。在鸿蒙OS中,开发悬浮窗功能需要理解系统权限、窗口管理和UI绘制等方面的知识。

本文将详细介绍如何在鸿蒙OS中实现悬浮窗功能,包含项目配置、权限申请、代码实现和调试优化。通过实际实例,帮助开发者掌握在鸿蒙OS中实现悬浮窗的完整流程。

实现步骤

I. 项目配置

  1. 创建鸿蒙OS工程

    • 首先,在鸿蒙OS开发工具中创建一个新的工程,并配置工程名称和包名。

  2. 配置权限

    • 在鸿蒙OS中使用悬浮窗需要申请系统权限。打开 config.json 文件,添加悬浮窗权限配置。

 {
   "module": {
     "abilities": [
       {
         "name": "MainAbility",
         "permissions": [
           "ohos.permission.SYSTEM_WINDOW"
         ]
       }
     ]
   }
 }

II. 界面布局

  1. 创建悬浮窗布局

    • 创建一个XML布局文件,用于定义悬浮窗的UI界面。

 <!-- resources/base/layout/floating_window_layout.xml -->
 <DirectionalLayout
     xmlns:ohos="http://schemas.huawei.com/res/ohos"
     ohos:width="match_parent"
     ohos:height="match_parent"
     ohos:orientation="vertical"
     ohos:padding="16vp"
     ohos:background_element="graphic:background">
 ​
     <Button
         ohos:id="$+id:close_button"
         ohos:width="match_content"
         ohos:height="match_content"
         ohos:text="Close"
         ohos:alignment="center"/>
 ​
     <Text
         ohos:width="match_parent"
         ohos:height="match_content"
         ohos:text="This is a floating window"
         ohos:text_size="20vp"
         ohos:alignment="center"/>
 </DirectionalLayout>

III. 悬浮窗实现

  1. 创建悬浮窗服务

    • 在鸿蒙OS中,悬浮窗通常由一个Service(AbilityService)来管理。创建一个悬浮窗服务类。

 import ohos.aafwk.ability.Ability;
 import ohos.aafwk.content.Intent;
 import ohos.agp.components.Component;
 import ohos.agp.components.ComponentContainer;
 import ohos.agp.components.LayoutScatter;
 import ohos.agp.window.service.Display;
 import ohos.agp.window.service.WindowManager;
 import ohos.bundle.IBundleManager;
 import ohos.rpc.RemoteException;
 ​
 public class FloatingWindowService extends Ability {
     private Component floatingView;
 ​
     @Override
     public void onStart(Intent intent) {
         super.onStart(intent);
         requestPermissions();
         initFloatingWindow();
     }
 ​
     private void requestPermissions() {
         if (verifySelfPermission("ohos.permission.SYSTEM_WINDOW") != IBundleManager.PERMISSION_GRANTED) {
             try {
                 requestPermissionsFromUser(new String[]{"ohos.permission.SYSTEM_WINDOW"}, 0);
             } catch (RemoteException e) {
                 e.printStackTrace();
             }
         }
     }
 ​
     private void initFloatingWindow() {
         WindowManager windowManager = WindowManager.getInstance();
         Display display = windowManager.getDefaultDisplay(this).orElseThrow();
         LayoutScatter layoutScatter = LayoutScatter.getInstance(this);
         floatingView = layoutScatter.parse(ResourceTable.Layout_floating_window_layout, null, false);
 ​
         WindowManager.LayoutConfig params = new WindowManager.LayoutConfig(
                 WindowManager.LayoutConfig.MATCH_PARENT,
                 WindowManager.LayoutConfig.MATCH_PARENT,
                 WindowManager.LayoutConfig.TYPE_SYSTEM_ALERT,
                 WindowManager.LayoutConfig.FLAG_NOT_FOCUSABLE
         );
 ​
         windowManager.addWindow(floatingView, params);
 ​
         floatingView.findComponentById(ResourceTable.Id_close_button).setClickedListener(component -> stopSelf());
     }
 ​
     @Override
     public void onStop() {
         WindowManager.getInstance().removeWindow(floatingView);
         super.onStop();
     }
 }
  1. 启动悬浮窗服务

    • 在主Ability中启动悬浮窗服务。

 import ohos.aafwk.ability.Ability;
 import ohos.aafwk.content.Intent;
 ​
 public class MainAbility extends Ability {
     @Override
     public void onStart(Intent intent) {
         super.onStart(intent);
         super.setMainRoute(MainAbilitySlice.class.getName());
 ​
         Intent serviceIntent = new Intent();
         serviceIntent.setOperation(new Intent.OperationBuilder()
                 .withDeviceId("")
                 .withBundleName(getBundleName())
                 .withAbilityName(FloatingWindowService.class.getName())
                 .build());
         startAbility(serviceIntent);
     }
 }

IV. 调试与优化

  1. 测试悬浮窗功能

    • 部署应用到鸿蒙OS设备上,启动应用,确认悬浮窗能够正常显示和关闭。

  2. 优化悬浮窗布局

    • 根据实际需求调整悬浮窗的布局和样式,使其符合应用的用户体验设计。

V. 实践案例

  1. 项目背景

    • 假设我们正在开发一款聊天应用,需要在收到新消息时显示悬浮窗提示用户。悬浮窗显示消息预览,并提供快捷回复按钮。

  2. 实现步骤

    • 配置权限 config.json 文件中添加悬浮窗权限配置。

     {
       "module": {
         "abilities": [
           {
             "name": "MainAbility",
             "permissions": [
               "ohos.permission.SYSTEM_WINDOW"
             ]
           }
         ]
       }
     }
    • 创建悬浮窗布局

     <!-- resources/base/layout/floating_window_layout.xml -->
     <DirectionalLayout
         xmlns:ohos="http://schemas.huawei.com/res/ohos"
         ohos:width="match_parent"
         ohos:height="match_parent"
         ohos:orientation="vertical"
         ohos:padding="16vp"
         ohos:background_element="graphic:background">
     ​
         <Text
             ohos:id="$+id:message_preview"
             ohos:width="match_parent"
             ohos:height="match_content"
             ohos:text="New Message"
             ohos:text_size="20vp"
             ohos:alignment="center"/>
     ​
         <Button
             ohos:id="$+id:reply_button"
             ohos:width="match_content"
             ohos:height="match_content"
             ohos:text="Reply"
             ohos:alignment="center"/>
     ​
         <Button
             ohos:id="$+id:close_button"
             ohos:width="match_content"
             ohos:height="match_content"
             ohos:text="Close"
             ohos:alignment="center"/>
     </DirectionalLayout>
    • 创建悬浮窗服务

     import ohos.aafwk.ability.Ability;
     import ohos.aafwk.content.Intent;
     import ohos.agp.components.Component;
     import ohos.agp.components.ComponentContainer;
     import ohos.agp.components.LayoutScatter;
     import ohos.agp.window.service.Display;
     import ohos.agp.window.service.WindowManager;
     import ohos.bundle.IBundleManager;
     import ohos.rpc.RemoteException;
     ​
     public class FloatingWindowService extends Ability {
         private Component floatingView;
     ​
         @Override
         public void onStart(Intent intent) {
             super.onStart(intent);
             requestPermissions();
             initFloatingWindow();
         }
     ​
         private void requestPermissions() {
             if (verifySelfPermission("ohos.permission.SYSTEM_WINDOW") != IBundleManager.PERMISSION_GRANTED) {
                 try {
                     requestPermissionsFromUser(new String[]{"ohos.permission.SYSTEM_WINDOW"}, 0);
                 } catch (RemoteException e) {
                     e.printStackTrace();
                 }
             }
         }
     ​
         private void initFloatingWindow() {
             WindowManager windowManager = WindowManager.getInstance();
             Display display = windowManager.getDefaultDisplay(this).orElseThrow();
             LayoutScatter layoutScatter = LayoutScatter.getInstance(this);
             floatingView = layoutScatter.parse(ResourceTable.Layout_floating_window_layout, null, false);
     ​
             WindowManager.LayoutConfig params = new WindowManager.LayoutConfig(
                     WindowManager.LayoutConfig.MATCH_PARENT,
                     WindowManager.LayoutConfig.MATCH_PARENT,
                     WindowManager.LayoutConfig.TYPE_SYSTEM_ALERT,
                     WindowManager.LayoutConfig.FLAG_NOT_FOCUSABLE
             );
     ​
             windowManager.addWindow(floatingView, params);
     ​
             floatingView.findComponentById(ResourceTable.Id_close_button).setClickedListener(component -> stopSelf());
             floatingView.findComponentById(ResourceTable.Id.reply_button).setClickedListener(component -> replyMessage());
         }
     ​
         private void replyMessage() {
             // 实现回复消息的逻辑
             HiLog.info(new HiLogLabel(HiLog.LOG_APP, 0x00201, "FloatingWindowService"), "Reply button clicked");
         }
     ​
         @Override
         public void onStop() {
             WindowManager.getInstance().removeWindow(floatingView);
             super.onStop();
         }
     }
 ```
 ​
 - **启动悬浮窗服务**
 ​
 ```java
 import ohos.aafwk.ability.Ability;
 import ohos.aafwk.content.Intent;
 ​
 public class MainAbility extends Ability {
     @Override
     public void onStart(Intent intent) {
         super.onStart(intent);
         super.setMainRoute(MainAbilitySlice.class.getName());
 ​
         Intent serviceIntent = new Intent();
         serviceIntent.setOperation(new Intent.OperationBuilder()
                 .withDeviceId("")
                 .withBundleName(getBundleName())
                 .withAbilityName(FloatingWindowService.class.getName())
                 .build());
         startAbility(serviceIntent);
     }
 }
 ```

VI. 总结

通过本文的详细讲解,开发者可以掌握在鸿蒙OS中实现悬浮窗功能的完整流程。从项目配置、权限申请到代码实现,逐步介绍了实现悬浮窗的关键步骤。通过实际示例,展示了悬浮窗的应用场景和实现方法,为开发者提供了有价值的参考。希望本文能够帮助开发者在鸿蒙OS中实现更多丰富的功能,提升应用的用户体验。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。