安卓基础(悬浮窗分级菜单和弹窗)
initializeViews()
初始化
把全部的按钮都弄出来
// 主菜单按钮ImageButton mainButton = floatingMenuView.findViewById(R.id.main_button);// 二级菜单按钮subButtons = new ImageButton[3];subButtons[0] = floatingMenuView.findViewById(R.id.sub_button_1);subButtons[1] = floatingMenuView.findViewById(R.id.sub_button_2);subButtons[2] = floatingMenuView.findViewById(R.id.sub_button_3);// 三级菜单按钮初始化thirdLevelButtons = new ImageButton[3][3];// 第一组三级按钮 (从子按钮1展开)thirdLevelButtons[0][0] = floatingMenuView.findViewById(R.id.third_level_1_1);thirdLevelButtons[0][1] = floatingMenuView.findViewById(R.id.third_level_1_2);thirdLevelButtons[0][2] = floatingMenuView.findViewById(R.id.third_level_1_3);// 第二组三级按钮 (从子按钮2展开)thirdLevelButtons[1][0] = floatingMenuView.findViewById(R.id.third_level_2_1);thirdLevelButtons[1][1] = floatingMenuView.findViewById(R.id.third_level_2_2);thirdLevelButtons[1][2] = floatingMenuView.findViewById(R.id.third_level_2_3);// 第三组三级按钮 (从子按钮3展开)thirdLevelButtons[2][0] = floatingMenuView.findViewById(R.id.third_level_3_1);thirdLevelButtons[2][1] = floatingMenuView.findViewById(R.id.third_level_3_2);thirdLevelButtons[2][2] = floatingMenuView.findViewById(R.id.third_level_3_3);
然后就用button.setVisibility(View.GONE);把全部二级菜单全部隐藏起来
for循环也把三级菜单隐藏起来
// 初始隐藏所有二级和三级菜单for (ImageButton button : subButtons) {button.setVisibility(View.GONE);}for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {thirdLevelButtons[i][j].setVisibility(View.GONE);}}
所有的按钮都设置一下点击监听一下
// 设置主按钮点击事件mainButton.setOnClickListener(v -> toggleMainMenu());// 设置各个二级按钮的点击事件subButtons[0].setOnClickListener(v -> toggleThirdLevelMenu(0));subButtons[1].setOnClickListener(v -> toggleThirdLevelMenu(1));subButtons[2].setOnClickListener(v -> toggleThirdLevelMenu(2));// 设置三级按钮点击事件for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {final int groupIndex = i;final int buttonIndex = j;thirdLevelButtons[i][j].setOnClickListener(v -> {// 处理三级按钮点击Toast.makeText(this, "点击了按钮组" + (groupIndex + 1) + "的第" + (buttonIndex + 1) + "个按钮", Toast.LENGTH_SHORT).show();});}}
在设置一下滑动监听
setupDragListener(mainButton);
123
├── toggleMainMenu()
│ ├── 展开/收起二级菜单
│ └── 控制动画
│
├── toggleThirdLevelMenu()
│ ├── 展开/收起三级菜单
│ └── 控制动画
│
├── hideThirdLevelMenu()
│ └── 隐藏指定组的三级菜单
│
└── onDestroy()└── 移除悬浮窗视图
123
完整代码
FloatingMenuService.java
package com.example.testtest;import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Build;
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.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageButton;
import android.widget.Toast;public class FloatingMenuService extends Service {private WindowManager windowManager;private View floatingMenuView;private WindowManager.LayoutParams params;private boolean isMenuExpanded = false;private ImageButton[] subButtons;private ImageButton[][] thirdLevelButtons;private boolean[] isThirdLevelExpanded = {false, false, false};private int initialX, initialY;private float initialTouchX, initialTouchY;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();// 初始化WindowManagerwindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);// 加载悬浮窗布局floatingMenuView = LayoutInflater.from(this).inflate(R.layout.floating_menu, null);// 设置窗口参数params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,getLayoutType(),WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,PixelFormat.TRANSLUCENT);params.gravity = Gravity.TOP | Gravity.START;params.x = 0;params.y = 100;// 添加视图到窗口windowManager.addView(floatingMenuView, params);// 初始化视图initializeViews();}private int getLayoutType() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {return WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;} else {return WindowManager.LayoutParams.TYPE_PHONE;}}private void initializeViews() {// 主菜单按钮ImageButton mainButton = floatingMenuView.findViewById(R.id.main_button);// 二级菜单按钮subButtons = new ImageButton[3];subButtons[0] = floatingMenuView.findViewById(R.id.sub_button_1);subButtons[1] = floatingMenuView.findViewById(R.id.sub_button_2);subButtons[2] = floatingMenuView.findViewById(R.id.sub_button_3);// 三级菜单按钮初始化thirdLevelButtons = new ImageButton[3][3];// 第一组三级按钮 (从子按钮1展开)thirdLevelButtons[0][0] = floatingMenuView.findViewById(R.id.third_level_1_1);thirdLevelButtons[0][1] = floatingMenuView.findViewById(R.id.third_level_1_2);thirdLevelButtons[0][2] = floatingMenuView.findViewById(R.id.third_level_1_3);// 第二组三级按钮 (从子按钮2展开)thirdLevelButtons[1][0] = floatingMenuView.findViewById(R.id.third_level_2_1);thirdLevelButtons[1][1] = floatingMenuView.findViewById(R.id.third_level_2_2);thirdLevelButtons[1][2] = floatingMenuView.findViewById(R.id.third_level_2_3);// 第三组三级按钮 (从子按钮3展开)thirdLevelButtons[2][0] = floatingMenuView.findViewById(R.id.third_level_3_1);thirdLevelButtons[2][1] = floatingMenuView.findViewById(R.id.third_level_3_2);thirdLevelButtons[2][2] = floatingMenuView.findViewById(R.id.third_level_3_3);// 初始隐藏所有二级和三级菜单for (ImageButton button : subButtons) {button.setVisibility(View.GONE);}for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {thirdLevelButtons[i][j].setVisibility(View.GONE);}}// 设置主按钮点击事件mainButton.setOnClickListener(v -> toggleMainMenu());// 设置各个二级按钮的点击事件subButtons[0].setOnClickListener(v -> toggleThirdLevelMenu(0));subButtons[1].setOnClickListener(v -> toggleThirdLevelMenu(1));subButtons[2].setOnClickListener(v -> toggleThirdLevelMenu(2));// 设置三级按钮点击事件for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {final int groupIndex = i;final int buttonIndex = j;thirdLevelButtons[i][j].setOnClickListener(v -> {// 处理三级按钮点击Toast.makeText(this, "点击了按钮组" + (groupIndex + 1) + "的第" + (buttonIndex + 1) + "个按钮", Toast.LENGTH_SHORT).show();});}}// 设置拖动事件setupDragListener(mainButton);}private void toggleMainMenu() {isMenuExpanded = !isMenuExpanded;// 如果要收起主菜单,也要收起所有三级菜单if (!isMenuExpanded) {// 收起所有三级菜单for (int i = 0; i < isThirdLevelExpanded.length; i++) {if (isThirdLevelExpanded[i]) {hideThirdLevelMenu(i, true);}}}if (isMenuExpanded) {// 展开菜单for (int i = 0; i < subButtons.length; i++) {ImageButton button = subButtons[i];button.setVisibility(View.VISIBLE);// 加载动画Animation animation = AnimationUtils.loadAnimation(this, R.anim.fade_in);animation.setStartOffset(i * 100); // 设置延迟,实现顺序展开效果button.startAnimation(animation);}} else {// 收起菜单for (int i = 0; i < subButtons.length; i++) {ImageButton button = subButtons[i];// 加载动画Animation animation = AnimationUtils.loadAnimation(this, R.anim.fade_out);animation.setStartOffset((subButtons.length - 1 - i) * 100); // 设置延迟,实现顺序收起效果button.startAnimation(animation);// 设置动画结束监听器final int index = i;animation.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {subButtons[index].setVisibility(View.GONE);}@Overridepublic void onAnimationRepeat(Animation animation) {}});button.startAnimation(animation);}}}private void toggleThirdLevelMenu(int groupIndex) {isThirdLevelExpanded[groupIndex] = !isThirdLevelExpanded[groupIndex];// 收起其他三级菜单for (int i = 0; i < isThirdLevelExpanded.length; i++) {if (i != groupIndex && isThirdLevelExpanded[i]) {hideThirdLevelMenu(i, false);isThirdLevelExpanded[i] = false;}}if (isThirdLevelExpanded[groupIndex]) {// 展开对应的三级菜单for (int i = 0; i < 3; i++) {ImageButton button = thirdLevelButtons[groupIndex][i];button.setVisibility(View.VISIBLE);// 加载动画Animation animation = AnimationUtils.loadAnimation(this, R.anim.fade_in);animation.setStartOffset(i * 70); // 设置较短的延迟,三级菜单展开稍快button.startAnimation(animation);}} else {// 收起对应的三级菜单hideThirdLevelMenu(groupIndex, false);}}private void hideThirdLevelMenu(int groupIndex, boolean immediately) {for (int i = 0; i < 3; i++) {ImageButton button = thirdLevelButtons[groupIndex][i];if (immediately) {button.clearAnimation();button.setVisibility(View.GONE);continue;}// 加载动画Animation animation = AnimationUtils.loadAnimation(this, R.anim.fade_out);animation.setStartOffset((3 - 1 - i) * 70); // 设置较短的延迟button.startAnimation(animation);// 设置动画结束监听器final int index = i;animation.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {thirdLevelButtons[groupIndex][index].setVisibility(View.GONE);}@Overridepublic void onAnimationRepeat(Animation animation) {}});button.startAnimation(animation);}}private void setupDragListener(View view) {view.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_MOVE:// 计算移动距离params.x = initialX + (int) (event.getRawX() - initialTouchX);params.y = initialY + (int) (event.getRawY() - initialTouchY);// 更新窗口位置windowManager.updateViewLayout(floatingMenuView, params);return true;case MotionEvent.ACTION_UP:// 如果移动距离很小,则视为点击int xDiff = (int) (event.getRawX() - initialTouchX);int yDiff = (int) (event.getRawY() - initialTouchY);if (Math.abs(xDiff) < 5 && Math.abs(yDiff) < 5) {v.performClick();}return true;}return false;}});}@Overridepublic void onDestroy() {super.onDestroy();if (floatingMenuView != null && windowManager != null) {windowManager.removeView(floatingMenuView);}}
}
MainActivity.java
package com.example.testtest;import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {private static final int OVERLAY_PERMISSION_CODE = 100;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button startButton = findViewById(R.id.start_floating_button);startButton.setOnClickListener(v -> checkOverlayPermission());}private void checkOverlayPermission() {// 检查是否已有悬浮窗权限if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {// 如果没有权限,请求权限Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,Uri.parse("package:" + getPackageName()));// Android 12之前使用startActivityForResultif (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {startActivityForResult(intent, OVERLAY_PERMISSION_CODE);} else {// Android 12及以上使用ActivityResultLaunchertry {overlayPermissionLauncher.launch(intent);} catch (Exception e) {Toast.makeText(this, "打开权限设置页面失败", Toast.LENGTH_SHORT).show();}}} else {// 已有权限,启动悬浮窗服务startFloatingMenuService();}}// 用于Android 12及以上版本的权限请求结果处理private final ActivityResultLauncher<Intent> overlayPermissionLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),result -> {// 检查用户是否授予了权限if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Settings.canDrawOverlays(this)) {startFloatingMenuService();} else {Toast.makeText(this, "需要悬浮窗权限才能使用此功能", Toast.LENGTH_SHORT).show();}});@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);// 处理Android 12之前的权限请求结果if (requestCode == OVERLAY_PERMISSION_CODE) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Settings.canDrawOverlays(this)) {startFloatingMenuService();} else {Toast.makeText(this, "需要悬浮窗权限才能使用此功能", Toast.LENGTH_SHORT).show();}}}private void startFloatingMenuService() {Intent serviceIntent = new Intent(MainActivity.this, FloatingMenuService.class);startService(serviceIntent);// 可选:启动服务后可以关闭Activity// finish();}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="16dp"tools:context=".MainActivity"><TextViewandroid:id="@+id/title_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:layout_marginTop="50dp"android:text="悬浮窗菜单示例"android:textSize="24sp"android:textStyle="bold" /><TextViewandroid:id="@+id/description_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@id/title_text"android:layout_marginTop="20dp"android:gravity="center"android:text="点击下方按钮启动带有菜单功能的悬浮窗"android:textSize="16sp" /><Buttonandroid:id="@+id/start_floating_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:padding="12dp"android:text="启动悬浮窗"android:textSize="18sp" /></RelativeLayout>
floating_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="16dp"><!-- 三级按钮组1 (显示在子按钮1下方) --><ImageButtonandroid:id="@+id/third_level_1_3"android:layout_width="40dp"android:layout_height="40dp"android:layout_below="@+id/sub_button_1"android:layout_marginTop="8dp"android:layout_alignEnd="@+id/sub_button_1"android:background="@drawable/circle_third_button_bg"android:contentDescription="@string/third_level_1_3"android:padding="8dp"android:visibility="gone"android:src="@drawable/ic_button_1" /><ImageButtonandroid:id="@+id/third_level_1_2"android:layout_width="40dp"android:layout_height="40dp"android:layout_below="@+id/sub_button_1"android:layout_marginTop="8dp"android:layout_marginEnd="8dp"android:layout_toStartOf="@+id/third_level_1_3"android:background="@drawable/circle_third_button_bg"android:contentDescription="@string/third_level_1_2"android:padding="8dp"android:visibility="gone"android:src="@drawable/ic_button_2" /><ImageButtonandroid:id="@+id/third_level_1_1"android:layout_width="40dp"android:layout_height="40dp"android:layout_below="@+id/sub_button_1"android:layout_marginTop="8dp"android:layout_marginEnd="8dp"android:layout_toStartOf="@+id/third_level_1_2"android:background="@drawable/circle_third_button_bg"android:contentDescription="@string/third_level_1_1"android:padding="8dp"android:visibility="gone"android:src="@drawable/ic_button_3" /><!-- 三级按钮组2 (显示在子按钮2下方) --><ImageButtonandroid:id="@+id/third_level_2_3"android:layout_width="40dp"android:layout_height="40dp"android:layout_below="@+id/sub_button_2"android:layout_marginTop="8dp"android:layout_alignEnd="@+id/sub_button_2"android:background="@drawable/circle_third_button_bg"android:contentDescription="@string/third_level_2_3"android:padding="8dp"android:visibility="gone"android:src="@drawable/ic_button_1" /><ImageButtonandroid:id="@+id/third_level_2_2"android:layout_width="40dp"android:layout_height="40dp"android:layout_below="@+id/sub_button_2"android:layout_marginTop="8dp"android:layout_marginEnd="8dp"android:layout_toStartOf="@+id/third_level_2_3"android:background="@drawable/circle_third_button_bg"android:contentDescription="@string/third_level_2_2"android:padding="8dp"android:visibility="gone"android:src="@drawable/ic_button_2" /><ImageButtonandroid:id="@+id/third_level_2_1"android:layout_width="40dp"android:layout_height="40dp"android:layout_below="@+id/sub_button_2"android:layout_marginTop="8dp"android:layout_marginEnd="8dp"android:layout_toStartOf="@+id/third_level_2_2"android:background="@drawable/circle_third_button_bg"android:contentDescription="@string/third_level_2_1"android:padding="8dp"android:visibility="gone"android:src="@drawable/ic_button_3" /><!-- 三级按钮组3 (显示在子按钮3下方) --><ImageButtonandroid:id="@+id/third_level_3_3"android:layout_width="40dp"android:layout_height="40dp"android:layout_below="@+id/sub_button_3"android:layout_marginTop="8dp"android:layout_alignEnd="@+id/sub_button_3"android:background="@drawable/circle_third_button_bg"android:contentDescription="@string/third_level_3_3"android:padding="8dp"android:visibility="gone"android:src="@drawable/ic_button_1" /><ImageButtonandroid:id="@+id/third_level_3_2"android:layout_width="40dp"android:layout_height="40dp"android:layout_below="@+id/sub_button_3"android:layout_marginTop="8dp"android:layout_marginEnd="8dp"android:layout_toStartOf="@+id/third_level_3_3"android:background="@drawable/circle_third_button_bg"android:contentDescription="@string/third_level_3_2"android:padding="8dp"android:visibility="gone"android:src="@drawable/ic_button_2" /><ImageButtonandroid:id="@+id/third_level_3_1"android:layout_width="40dp"android:layout_height="40dp"android:layout_below="@+id/sub_button_3"android:layout_marginTop="8dp"android:layout_marginEnd="8dp"android:layout_toStartOf="@+id/third_level_3_2"android:background="@drawable/circle_third_button_bg"android:contentDescription="@string/third_level_3_1"android:padding="8dp"android:visibility="gone"android:src="@drawable/ic_button_3" /><!-- 子按钮3 --><ImageButtonandroid:id="@+id/sub_button_3"android:layout_width="48dp"android:layout_height="48dp"android:layout_marginEnd="16dp"android:layout_toStartOf="@+id/sub_button_2"android:background="@drawable/circle_button_bg"android:contentDescription="@string/sub_button_3"android:padding="8dp"android:src="@drawable/ic_button_3" /><!-- 子按钮2 --><ImageButtonandroid:id="@+id/sub_button_2"android:layout_width="48dp"android:layout_height="48dp"android:layout_marginEnd="16dp"android:layout_toStartOf="@+id/sub_button_1"android:background="@drawable/circle_button_bg"android:contentDescription="@string/sub_button_2"android:padding="8dp"android:src="@drawable/ic_button_2" /><!-- 子按钮1 --><ImageButtonandroid:id="@+id/sub_button_1"android:layout_width="48dp"android:layout_height="48dp"android:layout_marginEnd="16dp"android:layout_toStartOf="@+id/main_button"android:background="@drawable/circle_button_bg"android:contentDescription="@string/sub_button_1"android:padding="8dp"android:src="@drawable/ic_button_1" /><!-- 主按钮 --><ImageButtonandroid:id="@+id/main_button"android:layout_width="56dp"android:layout_height="56dp"android:layout_alignParentEnd="true"android:background="@drawable/circle_main_button_bg"android:contentDescription="@string/main_button"android:padding="8dp"android:src="@drawable/ic_menu" /></RelativeLayout>
123
弹窗
1. 创建一个基本弹窗
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("提示").setMessage("确认删除吗?").setPositiveButton("确定", (dialog, which) -> {// 确定按钮点击逻辑Toast.makeText(this, "已删除", Toast.LENGTH_SHORT).show();}).setNegativeButton("取消", null).show();
2. 自定义布局弹窗
AlertDialog.Builder builder = new AlertDialog.Builder(this);// 加载自定义布局
View customView = LayoutInflater.from(this).inflate(R.layout.custom_dialog, null);
builder.setView(customView);AlertDialog dialog = builder.create();
dialog.show();// 绑定自定义布局中的组件
Button btnSubmit = customView.findViewById(R.id.btn_submit);
btnSubmit.setOnClickListener(v -> {dialog.dismiss(); // 关闭弹窗
});
容器
- 场景:当需要在一个弹窗中同时包含输入框、按钮、标题等多个组件时,容器可以将这些元素组织成一个整体。
- 优势:模块化的布局更易扩展和维护,例如后续新增一个按钮只需添加到容器中
// 创建容器并添加多个子视图
LinearLayout container = new LinearLayout(context);
container.setOrientation(LinearLayout.VERTICAL);
container.setPadding(50, 30, 50, 10);TextView title = new TextView(context);
title.setText("用户信息");
container.addView(title);EditText input = new EditText(context);
container.addView(input);Button submitBtn = new Button(context);
submitBtn.setText("提交");
container.addView(submitBtn);
设置监听
// 创建容器并添加多个子视图
LinearLayout container = new LinearLayout(context);
container.setOrientation(LinearLayout.VERTICAL);
container.setPadding(50, 30, 50, 10); // 注意:建议使用 dp 单位(见下文注意事项)TextView title = new TextView(context);
title.setText("用户信息");
container.addView(title);EditText input = new EditText(context);
container.addView(input);Button submitBtn = new Button(context);
submitBtn.setText("提交");// 设置点击监听
submitBtn.setOnClickListener(v -> {String text = input.getText().toString();if (!text.isEmpty()) {Toast.makeText(context, "提交内容:" + text, Toast.LENGTH_SHORT).show();} else {Toast.makeText(context, "请输入内容", Toast.LENGTH_SHORT).show();}
});container.addView(submitBtn);
改进后的MainActivity.java
package com.example.testtest;import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {private static final int OVERLAY_PERMISSION_CODE = 100;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button startButton = findViewById(R.id.start_floating_button);startButton.setOnClickListener(v -> checkOverlayPermission());}private void checkOverlayPermission() {// 检查是否已有悬浮窗权限if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {// 如果没有权限,请求权限Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,Uri.parse("package:" + getPackageName()));// Android 12之前使用startActivityForResultif (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {startActivityForResult(intent, OVERLAY_PERMISSION_CODE);} else {// Android 12及以上使用ActivityResultLaunchertry {overlayPermissionLauncher.launch(intent);} catch (Exception e) {Toast.makeText(this, "打开权限设置页面失败", Toast.LENGTH_SHORT).show();}}} else {// 已有权限,启动悬浮窗服务startFloatingMenuService();}}// 用于Android 12及以上版本的权限请求结果处理private final ActivityResultLauncher<Intent> overlayPermissionLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),result -> {// 检查用户是否授予了权限if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Settings.canDrawOverlays(this)) {startFloatingMenuService();} else {Toast.makeText(this, "需要悬浮窗权限才能使用此功能", Toast.LENGTH_SHORT).show();}});@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);// 处理Android 12之前的权限请求结果if (requestCode == OVERLAY_PERMISSION_CODE) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Settings.canDrawOverlays(this)) {startFloatingMenuService();} else {Toast.makeText(this, "需要悬浮窗权限才能使用此功能", Toast.LENGTH_SHORT).show();}}}private void startFloatingMenuService() {Intent serviceIntent = new Intent(MainActivity.this, FloatingMenuService.class);startService(serviceIntent);// 可选:启动服务后可以关闭Activity// finish();}
}