当前位置: 首页 > ds >正文

安卓基础(悬浮窗)

悬浮窗

import android.app.Service;
import android.content.Context;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;public class FloatingWindowService extends Service {private WindowManager windowManager;private View floatingView;@Overridepublic void onCreate() {super.onCreate();// 获取 WindowManager 对象windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);// 加载悬浮窗布局floatingView = LayoutInflater.from(this).inflate(R.layout.floating_window, null);// 设置悬浮窗的布局参数WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,android.graphics.PixelFormat.TRANSLUCENT);// 设置悬浮窗的位置params.gravity = Gravity.TOP | Gravity.START;params.x = 0;params.y = 100;// 将悬浮窗添加到 WindowManager 中windowManager.addView(floatingView, params);}@Overridepublic void onDestroy() {super.onDestroy();if (floatingView != null) {// 移除悬浮窗windowManager.removeView(floatingView);}}@Overridepublic IBinder onBind(android.content.Intent intent) {return null;}
}

参数说明

// 设置窗口的宽度,使其根据内部内容自动调整大小,能刚好包裹住内容
WindowManager.LayoutParams.WRAP_CONTENT, 
// 设置窗口的高度,同样使其根据内部内容自动调整大小,能刚好包裹住内容
WindowManager.LayoutParams.WRAP_CONTENT, 
// 指定窗口类型为应用覆盖层,可让窗口显示在其他应用之上(Android 8.0 及以上需特定权限)
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, 
// 设置窗口的标志位,让窗口不获取焦点,触摸事件可穿透传递给下方窗口
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, 
// 设置窗口的像素格式为半透明,窗口会呈现半透明效果,可看到下方内容
android.graphics.PixelFormat.TRANSLUCENT 

窗口管理.布局参数 参数 = 窗口管理.布局参数

(实例)窗口管理.添加视图(加载xml布局,参数)

悬浮窗拖拽功能

import android.app.Service;
import android.content.Context;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;public class FloatingWindowService extends Service {private WindowManager windowManager;private View floatingView;private WindowManager.LayoutParams params;private int initialX;private int initialY;private float initialTouchX;private float initialTouchY;@Overridepublic void onCreate() {super.onCreate();// 获取 WindowManager 对象windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);// 加载悬浮窗布局floatingView = LayoutInflater.from(this).inflate(R.layout.floating_window, null);// 设置悬浮窗的布局参数params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,android.graphics.PixelFormat.TRANSLUCENT);// 设置悬浮窗的位置params.gravity = Gravity.TOP | Gravity.START;params.x = 0;params.y = 100;// 将悬浮窗添加到 WindowManager 中windowManager.addView(floatingView, params);// 为悬浮窗设置触摸监听器以实现拖拽功能floatingView.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 记录初始位置和触摸点initialX = params.x;initialY = params.y;initialTouchX = event.getRawX();initialTouchY = event.getRawY();return true;case MotionEvent.ACTION_UP:return true;case MotionEvent.ACTION_MOVE:// 计算位置变化并更新悬浮窗位置params.x = initialX + (int) (event.getRawX() - initialTouchX);params.y = initialY + (int) (event.getRawY() - initialTouchY);windowManager.updateViewLayout(floatingView, params);return true;}return false;}});}@Overridepublic void onDestroy() {super.onDestroy();if (floatingView != null) {// 移除悬浮窗windowManager.removeView(floatingView);}}@Overridepublic IBinder onBind(android.content.Intent intent) {return null;}
}    

加载xml布局.设置触碰监听

MotionEvent event

event.getAction() //当前事件行动

MotionEvent.ACTION_DOWN

MotionEvent.ACTION_UP

MotionEvent.ACTION_MOVE

windowManager.updateViewLayout(floatingView, params); //悬浮窗更新


悬浮窗有两个按钮,一个是全截图,另一个是无障碍点击

floating_window.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"android:padding="8dp"><Buttonandroid:id="@+id/full_screenshot_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="全截图" /><Buttonandroid:id="@+id/perform_accessibility_click_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="执行无障碍点击" />
</LinearLayout>    

FloatingWindowService.java

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;public class FloatingWindowService extends Service {private WindowManager windowManager;private View floatingView;private WindowManager.LayoutParams params;private int initialX;private int initialY;private float initialTouchX;private float initialTouchY;@Overridepublic void onCreate() {super.onCreate();// 获取 WindowManager 对象windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);// 加载悬浮窗布局floatingView = LayoutInflater.from(this).inflate(R.layout.floating_window, null);// 设置悬浮窗的布局参数params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,android.graphics.PixelFormat.TRANSLUCENT);// 设置悬浮窗的位置params.gravity = Gravity.TOP | Gravity.START;params.x = 0;params.y = 100;// 将悬浮窗添加到 WindowManager 中windowManager.addView(floatingView, params);// 为悬浮窗设置触摸监听器以实现拖拽功能floatingView.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 记录初始位置和触摸点initialX = params.x;initialY = params.y;initialTouchX = event.getRawX();initialTouchY = event.getRawY();return true;case MotionEvent.ACTION_UP:return true;case MotionEvent.ACTION_MOVE:// 计算位置变化并更新悬浮窗位置params.x = initialX + (int) (event.getRawX() - initialTouchX);params.y = initialY + (int) (event.getRawY() - initialTouchY);windowManager.updateViewLayout(floatingView, params);return true;}return false;}});// 找到两个按钮并设置点击监听器Button fullScreenshotButton = floatingView.findViewById(R.id.full_screenshot_button);Button performAccessibilityClickButton = floatingView.findViewById(R.id.perform_accessibility_click_button);fullScreenshotButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 处理全截图逻辑,这里只是示例,需要根据实际情况实现// 比如调用截图方法performFullScreenshot();}});performAccessibilityClickButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 处理执行无障碍点击逻辑,这里只是示例,需要根据实际情况实现// 比如调用无障碍点击方法performAccessibilityClick();}});}private void performFullScreenshot() {// 这里实现全截图的具体逻辑// 例如使用 MediaProjection 进行截图// 由于代码较为复杂,这里只是占位// 你可以参考 Android 官方文档或相关教程来实现}private void performAccessibilityClick() {// 这里实现执行无障碍点击的具体逻辑// 例如通过 AccessibilityService 来模拟点击操作// 由于代码较为复杂,这里只是占位// 你可以参考 Android 官方文档或相关教程来实现}@Overridepublic void onDestroy() {super.onDestroy();if (floatingView != null) {// 移除悬浮窗windowManager.removeView(floatingView);}}@Overridepublic IBinder onBind(Intent intent) {return null;}
}    

从加载xml布局找到两个按钮

// 找到两个按钮并设置点击监听器
Button fullScreenshotButton = floatingView.findViewById(R.id.full_screenshot_button);
Button performAccessibilityClickButton = floatingView.findViewById(R.id.perform_accessibility_click_button);

两个按钮分别进行一个点击监听

fullScreenshotButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 处理全截图逻辑,这里只是示例,需要根据实际情况实现// 比如调用截图方法performFullScreenshot();}});performAccessibilityClickButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 处理执行无障碍点击逻辑,这里只是示例,需要根据实际情况实现// 比如调用无障碍点击方法performAccessibilityClick();}});}

http://www.xdnf.cn/news/3804.html

相关文章:

  • Java中深拷贝与浅拷贝的深入探讨
  • C++类_虚基类
  • IDEA快速上手Maven项目:模板选择 + 多模块拆分
  • Spring Boot 微服务打包为 Docker 镜像并部署到镜像仓库实战案例
  • 合成复用原则(CRP)
  • IDEA回滚代码操作
  • Windows下调试WebRTC源码
  • BOSS的收入 - 华为OD机试(A卷,C++题解)
  • 昇腾的昇思MindSpore是什么?跟TensorFlow/PyTorch 等第三方框架有什么区别和联系?【浅谈版】
  • c++ 二级指针 vs 指针引用
  • 小土堆pytorch数据加载概念以及实战
  • 【Tauri2】37——后端处理invoke
  • SVM实战:从理论到鸢尾花数据集的分类可视化
  • skynet中的client.socket库函数详解
  • WebRTC 服务器之Janus架构分析
  • 大模型开发的环节
  • AIGC算力消耗白皮书:Stable Diffusion vs Midjourney的架构成本差异
  • 头歌数据库课程实验(索引与数据库完整性)
  • 从零认识阿里云OSS:云原生对象存储的核心价值
  • 解析机器人 2.0.2 | 支持超过50种短视频平台的链接解析,无水印提取,多功能下载工具
  • 华为OD机试真题——智能驾驶(2025A卷:200分)Java/python/JavaScript/C/C++/GO最佳实现
  • 什么是函数重载?
  • MySQL 空值处理函数对比:IFNULL、COALESCE 和 NULLIF
  • 《Linux macOS :GCC升级方法》
  • 私人医生通过AI分析基因数据,是否有权提前告知癌症风险?
  • 【AI面试准备】XMind拆解业务场景识别AI赋能点
  • QML图像提供器 (Image Provider)
  • 【Ansible自动化运维实战:从Playbook到负载均衡指南】
  • 【算法基础】插入排序算法 - JAVA
  • 怎样增加AI对话的拟人化和增加同理心