安卓基础(悬浮窗分级菜单和弹窗)

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();
    }
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奶龙牛牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值