Android 一个悬浮按钮在整个APP

314 阅读3分钟

创建一个全局悬浮按钮并为其添加点击事件,在Android应用中可以通过使用WindowManager来实现。以下是创建悬浮按钮并为其添加点击事件的基本步骤:

  1. 定义悬浮按钮的布局: 创建一个XML布局文件,例如floating_button.xml,用于定义悬浮按钮的样式。

    xml
    <!-- res/layout/floating_button.xml -->
    <ImageButton
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/floatingButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_floating_button"
        android:background="@drawable/floating_button_background"
        android:contentDescription="@string/floating_button" />
    
  2. 在代码中添加和管理悬浮按钮: 在你的ActivityApplication类中,使用WindowManager添加一个悬浮View

    java
    import android.app.Activity;
    import android.graphics.PixelFormat;
    import android.view.Gravity;
    import android.view.View;
    import android.view.WindowManager;
    import android.widget.Button;
    
    public class FloatingButtonManager {
        private View floatingButton;
        private WindowManager windowManager;
        private WindowManager.LayoutParams params;
    
        public FloatingButtonManager(Activity activity) {
            floatingButton = activity.getLayoutInflater().inflate(R.layout.floating_button, null);
            windowManager = (WindowManager) activity.getSystemService(Activity.WINDOW_SERVICE);
    
            // 设置悬浮按钮的参数
            params = new WindowManager.LayoutParams(
                    WindowManager.LayoutParams.WRAP_CONTENT,
                    WindowManager.LayoutParams.WRAP_CONTENT,
                    WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                    PixelFormat.TRANSLUCENT);
            params.gravity = Gravity.TOP | Gravity.END;
            params.x = 0;
            params.y = 0; // 初始位置,可以根据需要调整
    
            // 添加按钮到窗口
            windowManager.addView(floatingButton, params);
    
            // 设置按钮的点击事件
            setupClickEvent();
        }
    
        private void setupClickEvent() {
            floatingButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // 处理点击事件
                    performClickAction();
                }
            });
        }
    
        public void updatePosition(int x, int y) {
            params.x = x;
            params.y = y;
            windowManager.updateViewLayout(floatingButton, params);
        }
    
        public void removeFloatingButton() {
            if (floatingButton != null) {
                windowManager.removeView(floatingButton);
                floatingButton = null;
            }
        }
    
        private void performClickAction() {
            // 点击按钮后执行的动作
            // 例如,打开一个新的Activity或显示一个对话框
        }
    }
    
  3. Activity中使用FloatingButtonManager: 在你的Activity中创建FloatingButtonManager的实例,并根据需要更新按钮位置或移除按钮。

    java
    public class MainActivity extends AppCompatActivity {
        private FloatingButtonManager floatingButtonManager;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            floatingButtonManager = new FloatingButtonManager(this);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if (floatingButtonManager != null) {
                floatingButtonManager.removeFloatingButton();
            }
        }
    }
    
  4. 确保在Activity销毁时移除悬浮按钮: 在ActivityonDestroy()方法中,确保移除悬浮按钮,以避免内存泄漏。

  5. 处理权限: 从Android 6.0(API级别23)开始,需要SYSTEM_ALERT_WINDOW权限来显示悬浮按钮。确保你的应用有这个权限,或者在运行时请求它。

  6. 测试: 在不同设备和Android版本上测试悬浮按钮的行为,确保它在整个应用中都能正确显示和响应点击事件。

android 怎么申请悬浮窗权限 在Android系统中,要申请悬浮窗权限,你需要确保你的应用目标SDK版本是23(Android 6.0 "Marshmallow")或更高,并且在Manifest文件中声明android.permission.SYSTEM_ALERT_WINDOW权限。

如果你的应用目标SDK版本是23或更高,系统会默认启用“权限权限”模型,你需要在运行时请求用户授权。

以下是如何在代码中请求权限的示例:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (!Settings.canDrawOverlays(context)) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                Uri.parse("package:" + context.getPackageName()));
        startActivityForResult(intent, REQUEST_CODE); // REQUEST_CODE是你的自定义请求码
    }
}

onActivityResult()方法中检查结果:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_CODE) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (Settings.canDrawOverlays(context)) {
                // 用户允许了权限,现在可以创建悬浮窗了
            } else {
                // 用户拒绝了权限
            }
        }
    }
}

确保你的应用在Manifest文件中也声明了android.permission.SYSTEM_ALERT_WINDOW权限:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

用户只有在第一次请求权限时才会看到权限对话框,之后系统会记住用户的选择。如果用户之前已经拒绝了权限请求,你需要引导用户去系统设置中手动开启。

package com.huawo.module_interaction.debug;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;


import com.huawo.module_interaction.R;
//import com.lzf.easyfloat.EasyFloat;
//import com.lzf.easyfloat.enums.ShowPattern;
//import com.lzf.easyfloat.enums.SidePattern;

import me.goldze.mvvmhabit.utils.ToastUtils;

public class FloatingButtonManager {
private View floatingButton;
private WindowManager windowManager;
public FloatingButtonManager(Context context) {
    this.floatingButton = View.inflate(context, R.layout.floating_button, null);
    this.windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

    // 设置悬浮按钮的参数
    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT
    );
    params.gravity = Gravity.TOP | Gravity.START;
    params.x = 0;
    params.y = 130; // 初始Y坐标,可根据需要调整

    // 添加按钮到窗口
    windowManager.addView(floatingButton, params);
    Log.e("caixin","初始化FloatingButtonManager");
    // 设置按钮的点击事件
    floatingButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // 处理点击事件
            //                ToastUtils.showShort("点到了");
            DebugDialogManager.newInstance().showDialog(context);
        }
    });
}


public void checkpermission(Activity context){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (!Settings.canDrawOverlays(context)) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + context.getPackageName()));
            context.startActivityForResult(intent, 666); // REQUEST_CODE是你的自定义请求码
        }
    }
}

// 根据需要更新按钮位置
public void updatePosition(int x, int y) {
    WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams) floatingButton.getLayoutParams();
    layoutParams.x = x;
    layoutParams.y = y;
    windowManager.updateViewLayout(floatingButton, layoutParams);
}

// 移除按钮
public void removeFloatingButton() {
    if (floatingButton != null) {
        windowManager.removeView(floatingButton);
    }
}

}