在Android中想要创建悬浮窗分为三步
1.申请权限
2.使用服务启动悬浮窗
3.设置悬浮窗参数并添加进WindowManager
下面话不多说了,来一起看看详细的实现过程
申请权限
首先需要申请悬浮窗权限,在清单文件中 manifest 下添加
在Activity中动态申请权限
public class MainActivity extends Activity { /** 悬浮窗权限标识码 */ public static final int CODE_WINDOW = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 申请悬浮窗权限 if (Build.VERSION.SDK_INT >= 23) { if (!Settings.canDrawOverlays(this)) { Toast.makeText(this, "请打开此应用悬浮窗权限-Shendi", Toast.LENGTH_SHORT).show(); startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), CODE_WINDOW); } } // 关闭当前activity,这样只显示悬浮窗 finish(); } // 权限申请成功后的回调 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { // 不给权限就退出 case Permission.CODE_WINDOW: if (resultCode != Activity.RESULT_OK) System.exit(0); break; default: Toast.makeText(this, "未知权限回调: " + requestCode, Toast.LENGTH_SHORT).show(); } } }
使用服务启动悬浮窗
对于悬浮窗的操作主要使用 WindowManager
创建一个服务,并在清单文件中注册
public class TestService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { return null; } }
在清单文件的Application中注册服务
在Activity中启动服务
Intent intent = new Intent(this, TestService.class); startService(intent);
接下来需要创建悬浮窗的界面,这里方便演示直接使用代码创建
也可以使用inflate函数将xml文件变view对象
View.inflate(context, R.layout.main_activity, null);
在服务的onStartCommand函数中内容如下
@Override public int onStartCommand(Intent intent, int flags, int startId) { Button btn = new Button(this); btn.setText("hello,world"); return super.onStartCommand(intent, flags, startId); }
设置悬浮窗参数并添加进WindowManager
这里直接上代码,看注释
@Override public int onStartCommand(Intent intent, int flags, int startId) { Button btn = new Button(this); btn.setText("hello,world"); // 获取WindowManager WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); // 创建布局参数 WindowManager.LayoutParams params = new WindowManager.LayoutParams(); /** 设置参数 */ params.type = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY : WindowManager.LayoutParams.TYPE_PHONE; params.format = PixelFormat.RGBA_8888; // 设置窗口的行为准则 params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; //设置透明度 params.alpha = 1.0f; //设置内部视图对齐方式,这边位置为左边靠上 params.gravity = Gravity.LEFT | Gravity.TOP; //窗口的左上角坐标 params.x = 0; params.y = 0; //设置窗口的宽高,这里为自动 params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.height = WindowManager.LayoutParams.WRAP_CONTENT; // 添加进WindowManager wm.addView(btn, params); return super.onStartCommand(intent, flags, startId); }
完整代码如下
TestActivity
package shendi.app.game.robot; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.Settings; import android.widget.Toast; public class TestActivity extends Activity { /** 悬浮窗权限标识码 */ public static final int CODE_WINDOW = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 申请悬浮窗权限 if (Build.VERSION.SDK_INT >= 23) { if (!Settings.canDrawOverlays(this)) { Toast.makeText(this, "请打开此应用悬浮窗权限-Shendi", Toast.LENGTH_SHORT).show(); startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), CODE_WINDOW); } } Intent intent = new Intent(this, TestService.class); startService(intent); // 关闭当前activity,这样只显示悬浮窗 finish(); } // 权限申请成功后的回调 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { // 不给权限就退出 case Permission.CODE_WINDOW: if (resultCode != Activity.RESULT_OK) System.exit(0); break; default: Toast.makeText(this, "未知权限回调: " + requestCode, Toast.LENGTH_SHORT).show(); } } }
TestService
package shendi.app.game.robot; 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.WindowManager; import android.widget.Button; public class TestService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { Button btn = new Button(this); btn.setText("hello,world"); // 获取WindowManager WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); // 创建布局参数 WindowManager.LayoutParams params = new WindowManager.LayoutParams(); /** 设置参数 */ params.type = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY : WindowManager.LayoutParams.TYPE_PHONE; params.format = PixelFormat.RGBA_8888; // 设置窗口的行为准则 params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; //设置透明度 params.alpha = 1.0f; //设置内部视图对齐方式,这边位置为左边靠上 params.gravity = Gravity.LEFT | Gravity.TOP; //窗口的左上角坐标 params.x = 0; params.y = 0; //设置窗口的宽高,这里为自动 params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.height = WindowManager.LayoutParams.WRAP_CONTENT; // 添加进WindowManager wm.addView(btn, params); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { return null; } }
运行 app,可以在屏幕左上角看到 hello,world的按钮悬浮
拖动效果
给悬浮组件添加触碰事件可以实现拖动效果,按钮组件不适用
这里给出简单的实现代码片段
private int upX, upY; // 视图移动处理 view.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: upX = (int) event.getRawX(); upY = (int) event.getRawY(); break; case MotionEvent.ACTION_MOVE: // 与上一次位置相差不到5则不移动 if (event.getRawX() - upX > 5 || event.getRawY() - upY > 5) { params.x = (int) event.getRawX(); params.y = (int) event.getRawY(); wm.updateViewLayout(view, params); } break; case MotionEvent.ACTION_UP: // 相差不到5则代表点击 if (event.getRawX() - upX < 5 && event.getRawY() - upY < 5) { // TODO } break; } return false; } });
移除悬浮窗
可以在 onDestry 函数中进行移除
@Override public void onDestroy() { wm.removeView(view); super.onDestroy(); }
总结
到此这篇关于Android创建悬浮窗的文章就介绍到这了,更多相关Android悬浮窗内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!