1、Mainfest.xml文件中添加权限声明:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
添加之后如果点击打开悬浮窗,提示用户调转到权限打开界面后,用户可以点击开启权限,否则用户不可操作
2、申请权限,需要用户授权同意,代码如下:
public void startFloatService() {
if (!Settings.canDrawOverlays(this)) {
Toast.makeText(this, "当前无权限,退出", Toast.LENGTH_LONG).show();
startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName())), 0);
} else {
startService(new Intent(this, FlowWindowService.class));
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 0) {
if (!Settings.canDrawOverlays(this)) {
Toast.makeText(this, "授权失败.", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "授权成功.", Toast.LENGTH_SHORT).show();
startService(new Intent(this, FlowWindowService.class));
}
}
}
3、在service启动界面,设置如下:
private void showFloatWindow() {
if (Settings.canDrawOverlays(this)) {
Log.d(TAG, "showFloatWindow: ");
// 设置LayoutParam
mLayoutParams = new WindowManager.LayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
}
// 自定义View布局,悬浮框布局定制
View view = View.inflate(this, R.layout.sharing_layout, null);
mFloatingOnTouchListener = new FloatingOnTouchListener();
view.setOnTouchListener(mFloatingOnTouchListener);
mStartSharingBtn = view.findViewById(R.id.start_sharing_btn);
mStopSharingBtn = view.findViewById(R.id.end_sharing_btn);
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
Point point = new Point();
windowManager.getDefaultDisplay().getSize(point);
int screenWidth = point.x;
int screenHeight = point.y;
mLayoutParams.format = PixelFormat.RGBA_8888;
mLayoutParams.width = view.getMeasuredWidth();
mLayoutParams.height = view.getMeasuredHeight();
mLayoutParams.x = 0;
mLayoutParams.y = 0;
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
// 将悬浮窗控件添加到WindowManager
windowManager.addView(view, mLayoutParams);
Toast.makeText(this, "显示悬浮框", Toast.LENGTH_LONG).show();
}
}
private class FloatingOnTouchListener implements View.OnTouchListener {
private int x;
private int y;
boolean isMoving = false;
static final int move_offset = 5;
@Override
public boolean onTouch(View view, MotionEvent event) {
Log.d(TAG, "onTouch: action = " + event.getAction());
Log.d(TAG, "onTouch: x = " + event.getX() + ", y = " + event.getY());
Log.d(TAG, "onTouch: x = " + event.getRawX() + ", y = " + event.getRawY());
Log.d(TAG, "onTouch: startBtn x = " + mStartSharingBtn.getX() + ", y =" + mStartSharingBtn.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x = (int) event.getX();
y = (int) event.getY();
isMoving = false;
break;
case MotionEvent.ACTION_MOVE:
int nowX = (int) event.getX();
int nowY = (int) event.getY();
int movedX = nowX - x;
int movedY = nowY - y;
x = nowX;
y = nowY;
if (!isMoving && (Math.abs(movedX) >= move_offset ||
Math.abs(movedY) >= move_offset)) {
isMoving = true;
}
if (isMoving) {
mLayoutParams.x = mLayoutParams.x + movedX;
mLayoutParams.y = mLayoutParams.y + movedY;
windowManager.updateViewLayout(view, mLayoutParams);
}
return true;
case MotionEvent.ACTION_UP:
// 通过位置实现按钮点击事件;实现拖拽和滑动功能
Log.d(TAG, "onTouch: UP isMoving = " + isMoving);
if (!isMoving) {
if (x < mStartSharingBtn.getX() + mStartSharingBtn.getWidth()) {
Toast.makeText(FlowWindowService.this,
"start sharing.", Toast.LENGTH_SHORT).show();
} else if (x > mStopSharingBtn.getX()) {
Toast.makeText(FlowWindowService.this,
"stop sharing.", Toast.LENGTH_SHORT).show();
}
}
return isMoving;
}
return false;
}
}
参考资料:
https://blog.csdn.net/dongzhong1990/article/details/80512706