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;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
// 初始化WindowManager
windowManager = (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() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
subButtons[index].setVisibility(View.GONE);
}
@Override
public 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() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
thirdLevelButtons[groupIndex][index].setVisibility(View.GONE);
}
@Override
public void onAnimationRepeat(Animation animation) {}
});
button.startAnimation(animation);
}
}
private void setupDragListener(View view) {
view.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_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;
}
});
}
@Override
public 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;
@Override
protected 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之前使用startActivityForResult
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
startActivityForResult(intent, OVERLAY_PERMISSION_CODE);
} else {
// Android 12及以上使用ActivityResultLauncher
try {
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();
}
}
);
@Override
protected 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">
<TextView
android: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" />
<TextView
android: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" />
<Button
android: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下方) -->
<ImageButton
android: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" />
<ImageButton
android: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" />
<ImageButton
android: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下方) -->
<ImageButton
android: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" />
<ImageButton
android: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" />
<ImageButton
android: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下方) -->
<ImageButton
android: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" />
<ImageButton
android: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" />
<ImageButton
android: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 -->
<ImageButton
android: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 -->
<ImageButton
android: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 -->
<ImageButton
android: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" />
<!-- 主按钮 -->
<ImageButton
android: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;
@Override
protected 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之前使用startActivityForResult
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
startActivityForResult(intent, OVERLAY_PERMISSION_CODE);
} else {
// Android 12及以上使用ActivityResultLauncher
try {
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();
}
}
);
@Override
protected 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();
}
}