Android 可任意位置移动的悬浮窗

 1.悬浮窗权限申请

悬浮窗口的权限为Settings.ACTION_MANAGE_OVERLAY_PERMISSION

需要在代码中动态申请,而且需要用户到设置页面自行确认,然后在activity或者其他申请的位置使用回调,继续判断该权限是否申请成功。

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
   if (!Settings.canDrawOverlays(getApplicationContext())) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
        startActivityForResult(intent, 0);
    } else {
        mIntent = new Intent(MainActivity.this/*需要启动service的activity*/, FloatWindowService.class/*需要启动的service*/);
        bindService(mIntent, serviceConnection, Context.BIND_AUTO_CREATE);//直接启动服务方式启动
    }
}

private ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
    
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
};

在Activity回调申请权限的结果:

@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data){
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 0) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (Settings.canDrawOverlays(this)) {
                Intent mIntent = new Intent(MainActivity.this,FloatWindowService.class);
                startService(mIntent);//直接启动服务方式启动
            }
        }
    }
}

Intent mIntent = new Intent(MainActivity.this,XXXXXX.class);

startService(mIntent);//直接启动服务方式启动

2.创建悬浮窗:

使用创建service页面getSystemService(WINDOW_SERVICE),然后创建View

LayoutInflater.from(getApplication())加载自定义布局

wp = new WindowManager.LayoutParams();
mWindowManager = (WindowManager) getApplication().getSystemService(WINDOW_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
	wp.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
	wp.type = WindowManager.LayoutParams.TYPE_PHONE;
}
wp.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;//悬浮窗外部可点击
wp.gravity = Gravity.LEFT | Gravity.TOP;//悬浮窗弹出显示位置
wp.x = 0;
wp.y = 0;

wp.width = WindowManager.LayoutParams.WRAP_CONTENT;
wp.height = WindowManager.LayoutParams.WRAP_CONTENT;

LayoutInflater inflater = LayoutInflater.from(getApplication());
mFloatLayout = (LinearLayout) inflater.inflate(R.layout.float_window, null, false);
View view = mFloatLayout.findViewById(R.id.playMonitor);//自定义悬浮窗布局
view.setOnTouchListener(this);//设置移动监听,此处view是自定义充满布局的控件
mWindowManager.addView(mFloatLayout, wp);

3.设置滑动监听:

如果要移动悬浮窗口的位置,还需要重新onTouch方法或者dispatchTouchEvent方法,然后通过开始触摸点和移动触摸点计算出最终停留的位置

private int mTouchStartX, mTouchStartY, mStartX, mStartY, mTouchCurrentX, mTouchCurrentY;

@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
	switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			mTouchStartX = (int) event.getRawX();
			mTouchStartY = (int) event.getRawY();
			mStartX = (int) event.getX();
			mStartY = (int) event.getY();
			break;
		case MotionEvent.ACTION_MOVE:
			mTouchCurrentX = (int) event.getRawX();
			mTouchCurrentY = (int) event.getRawY();
			wp.x += mTouchCurrentX - mTouchStartX;
			wp.y += mTouchCurrentY - mTouchStartY;
			mWindowManager.updateViewLayout(mFloatLayout, wp);

			mTouchStartX = mTouchCurrentX;
			mTouchStartY = mTouchCurrentY;
	}
	return true;
}

4.PS:这里悬浮窗在service中实现,多用作媒体播放器,app不在栈顶时的任务管理等场景。Demo:https://download.csdn.net/download/mozushixin_1/12966330

有问题可以邮件交流。(E-mail:mozushixin@163.com)

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不会写代码的猴子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值