Android 悬浮窗使用

一、添加权限如下

<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();//关闭界面
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值