一、添加权限如下
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
二、以Service为依赖弹出悬浮窗【MWindowService】(需要在manifests中注册)
import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import com.driver.forever.R;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
/**
* CreateTime 2018/2/8 15:35
* Author LiuShiHua
* Description:
*/
public class MWindowService extends Service {
//Log用的TAG
private static final String TAG = "--------->";
private LinearLayout linearLayout;
//布局参数.
private WindowManager.LayoutParams params;
//实例化的WindowManager.
private WindowManager windowManager;
private ImageButton imageButton1;
//状态栏高度.(接下来会用到)
private int statusBarHeight = -1;
@Override
public void onCreate() {
super.onCreate();
createToucher();
}
private void createToucher() {
//赋值WindowManager&LayoutParam.
params = new WindowManager.LayoutParams();
windowManager = (WindowManager) getApplication().getSystemService(Context.WINDOW_SERVICE);
//设置type.系统提示型窗口,一般都在应用程序窗口之上.
params.type = TYPE_SYSTEM_ALERT;
//设置效果为背景透明.
params.format = PixelFormat.RGBA_8888;
//设置flags.不可聚焦及不可使用按钮对悬浮窗进行操控.
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
//设置窗口初始停靠位置.
params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
params.x = 0;
params.y = 30;
//设置悬浮窗口长宽数据.
//注意,这里的width和height均使用px而非dp.这里我偷了个懒
//如果你想完全对应布局设置,需要先获取到机器的dpi
//px与dp的换算为px = dp * (dpi / 160).
params.width = 300;
params.height = 300;
LayoutInflater inflater = LayoutInflater.from(getApplication());
//获取浮动窗口视图所在布局.
linearLayout = (LinearLayout) inflater.inflate(R.layout.dialog_window, null);
//添加toucherlayout
windowManager.addView(linearLayout, params);
Log.i(TAG, "left:" + linearLayout.getLeft());
Log.i(TAG, "right:" + linearLayout.getRight());
Log.i(TAG, "top:" + linearLayout.getTop());
Log.i(TAG, "bottom:" + linearLayout.getBottom());
//主动计算出当前View的宽高信息.
linearLayout.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
//用于检测状态栏高度.
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = getResources().getDimensionPixelSize(resourceId);
}
Log.i(TAG, "状态栏高度为:" + statusBarHeight);
//浮动窗口按钮.
imageButton1 = (ImageButton) linearLayout.findViewById(R.id.image);
imageButton1.setOnClickListener(new View.OnClickListener() {//双击退出
@Override
public void onClick(View v) {
AlertDialog dialog = new AlertDialog.Builder(MWindowService.this)
.setTitle("是否确认退出?")
.setNegativeButton("取消", null)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
stopSelf();
}
}).create();
dialog.getWindow().setType((WindowManager.LayoutParams.TYPE_SYSTEM_ALERT));//调用系统dialog
dialog.show();
}
});
linearLayout.setOnTouchListener(new View.OnTouchListener() {//拖动布局
@Override
public boolean onTouch(View v, MotionEvent event) {
//ImageButton我放在了布局中心,布局一共300dp
params.x = (int) event.getRawX() - 300;
//这就是状态栏偏移量用的地方
params.y = (int) event.getRawY() - 150 - statusBarHeight;
windowManager.updateViewLayout(linearLayout, params);
return false;
}
});
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
//用imageButton检查悬浮窗还在不在,这里可以不要。优化悬浮窗时要用到。
if (imageButton1 != null) {
windowManager.removeView(linearLayout);
}
super.onDestroy();
}
}
三、调用
在主Activity中点击事件中添加:
Intent in = new Intent(MainActivity.this, MWindowService.class);
startService(in);
finish();//关闭界面