悬浮窗
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;
@Override
public 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);
}
@Override
public void onDestroy() {
super.onDestroy();
if (floatingView != null) {
// 移除悬浮窗
windowManager.removeView(floatingView);
}
}
@Override
public 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;
@Override
public 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() {
@Override
public 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;
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
if (floatingView != null) {
// 移除悬浮窗
windowManager.removeView(floatingView);
}
}
@Override
public 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">
<Button
android:id="@+id/full_screenshot_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="全截图" />
<Button
android: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;
@Override
public 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() {
@Override
public 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() {
@Override
public void onClick(View v) {
// 处理全截图逻辑,这里只是示例,需要根据实际情况实现
// 比如调用截图方法
performFullScreenshot();
}
});
performAccessibilityClickButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 处理执行无障碍点击逻辑,这里只是示例,需要根据实际情况实现
// 比如调用无障碍点击方法
performAccessibilityClick();
}
});
}
private void performFullScreenshot() {
// 这里实现全截图的具体逻辑
// 例如使用 MediaProjection 进行截图
// 由于代码较为复杂,这里只是占位
// 你可以参考 Android 官方文档或相关教程来实现
}
private void performAccessibilityClick() {
// 这里实现执行无障碍点击的具体逻辑
// 例如通过 AccessibilityService 来模拟点击操作
// 由于代码较为复杂,这里只是占位
// 你可以参考 Android 官方文档或相关教程来实现
}
@Override
public void onDestroy() {
super.onDestroy();
if (floatingView != null) {
// 移除悬浮窗
windowManager.removeView(floatingView);
}
}
@Override
public 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() {
@Override
public void onClick(View v) {
// 处理全截图逻辑,这里只是示例,需要根据实际情况实现
// 比如调用截图方法
performFullScreenshot();
}
});
performAccessibilityClickButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 处理执行无障碍点击逻辑,这里只是示例,需要根据实际情况实现
// 比如调用无障碍点击方法
performAccessibilityClick();
}
});
}