悬浮窗教程,很简单。知识点不多,写下来 总结一下。

权限

首先 是在AndroidManiFest.xml 定义权限

如果 Android版本大于6.0 ,还需要引导用户 同意这个权限才行。并不是 你定义了就会给你的。

       //判断是否 有悬浮窗的权限        if (!Settings.canDrawOverlays(getApplicationContext())) {            Intent alertOver = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));             //这个页面不会返回值  所以用这个            startActivity(alertOver);        }

创建悬浮窗

下面这段代码 ,你可以直接复制到你的项目里面 运行。记得要申请权限!!!!

    @SuppressLint("ClickableViewAccessibility")    void initShow() {        //获取服务        WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);        // 设定参数        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();        //Android 8  对悬浮窗 进行了 改变        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {            layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;        } else {            layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;        }        //设置位图格式 默认是不透明的        layoutParams.format = PixelFormat.TRANSPARENT;        //设置宽 高  可以是MATCH_PARENT ,WRAP_CONTENT ,或者 确切的数值        layoutParams.width =300;        layoutParams.height = 300;        //设置悬浮窗 位置,这个受layoutParams.gravity 影响,它提供了从给定边缘的偏移量。        // 也就是说 这个悬浮窗的实际x,y位置。是这里x,y 加上偏移量后的。        layoutParams.x = 300;        layoutParams.y = 300;        //View以外的区域可以响应点击和触摸事件        layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;        //容器与小部件之间的水平边距,作为容器宽度的百分比。        // 通俗的讲 ,就是悬浮窗会在 x,y位置的那个方向,影响 layoutParams.x ,layoutParams.y的偏移量        //这个默认是AXIS_X_SHIFT   NO_GRAVITY        //将悬浮窗原点坐标系与屏幕重合  就是 把悬浮窗变成和普通view一样 都是以左上角为原点        //这个很重要        layoutParams.gravity = Gravity.LEFT | Gravity.TOP;         //创建view  就是悬浮窗里面的内容        TextView textView = new android.support.v7.widget.AppCompatTextView(getApplicationContext()){            @Override            public boolean performClick() {                return super.performClick();            }        };        textView.setText("我是悬浮窗");        //给view添加触摸事件,来使用悬浮窗可以移动        textView.setOnTouchListener(new View.OnTouchListener() {            //这个用于保存 当手指按下时候,离悬浮窗左上角的 x,y距离,这里设定初始值 是悬浮窗宽高的一半            float inX =layoutParams.width>>1, inY = layoutParams.height>>1;            @Override            public boolean onTouch(View v, MotionEvent event) {                switch (event.getAction()) {                    case MotionEvent.ACTION_DOWN:                        //得到 点击位置 在悬浮窗中的位置                        inX = event.getX();                        inY = event.getY();                        break;                    case MotionEvent.ACTION_MOVE:                        //得到当前滑动位置,在整个屏幕上面的坐标                        float nowX = event.getRawX();                        float nowY = event.getRawY();                        Zprint.log(this.getClass()," inX inY",inX,inY,nowX,nowY);                        //屏幕X坐标 减去 点击时候 在悬浮窗中的位置 X 距离                        layoutParams.x= (int) (nowX-inX);                        //屏幕高度坐标 要注意 状态栏高度                        layoutParams.y = (int) (nowY-statusHeight-inY);                        //更新悬浮窗 位置                        windowManager.updateViewLayout(textView, layoutParams);                        break;                }                return false;            }        });        //这下面代码只是说明 在悬浮窗里面的view 与在activity里面的view ,没有任何不同        textView.setOnClickListener(v -> textView.setText("点击了"));        textView.setBackgroundColor(getColor(android.R.color.darker_gray));        //添加view        windowManager.addView(textView, layoutParams);    }

首先,是获得windowManager,设置activity的宽高 也是通过这个类来实现的。获取这个实例的方式是通过getSystemService(WINDOW_SERVICE)在activity中的 也可以通过getWindowManager()来获取。
接着,就new 一个WindowManager.LayoutParams 布局参数。这个主要设置 悬浮窗的大小,类型(注意Android8),位置,位图之类的。上面 解释很清楚。如果不懂的 评论。
其次,就可以创建一个View 填充悬浮窗的内容。这个View既可以动态生成,也可以用xml写好,再用 LayoutInflater 实例出来这个View和在activity中的view 并没有什么区别!!!
最后 调用添加view就可以了。

更新悬浮窗位置

使用windowManager.updateViewLayout(View, ViewGroup.LayoutParams);来更新悬浮窗的位置。我们可以给悬浮窗里面的view 添加触摸事件 ,来获取触摸位置,更新悬浮窗,我上面那段触摸事件 可以实现当你按住悬浮窗任意一个位置时候,拖动悬浮窗,离开悬浮窗时候,手指最后离开悬浮窗中的位置是和一开始按住悬浮窗中的位置 是一样的
要注意 状态栏高度,ViewGroup.LayoutParams的x,y坐标是以状态栏和屏幕左边的交点为原点的。而getRaxY() 得到的是距离屏幕左上角的x,y坐标。

获取状态栏高度:

  public int getStatusBarHeight() {         //局部变量 声明后,要赋值,不像成员变量会有默认值        int result = 0;        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");        if (resourceId > 0) {            result = getResources().getDimensionPixelSize(resourceId);        }        return result;    }

更新悬浮窗内容

更新悬浮窗内容,就和在activity中更新view一样。找到view的实例进行更新view即可。记住要在主线程中

附 得到Android主线程

   //handler 持有主线程的looper  private Handler mainHandler = new Handler(getMainLooper(), new Handler.Callback() {        @Override        public boolean handleMessage(Message msg) {             //这里接收处理mainHandler 发送来的message              //在这里写实际在主线程中运行的代码            return false;        }    });    //在你要更新view的地方,或者需要主线程操作的地方 发送message     mainHandler.sendMessage(Message)

如果 你感觉上面代码 还是繁琐,也可以调用handler的post(Runnable)方法

mainHandler.post(Runnable r)

更多相关文章

  1. ubuntu环境下我的第一个android apk (2014.12.12更新)
  2. 自己祝贺一下访问量突破10000,发几个android的资料介绍(持续更新)
  3. 自己祝贺一下访问量突破10000,发几个android的资料介绍(持续更新)
  4. 如何申请 android google map API key
  5. Android移动view动画问题
  6. android异步更新UI
  7. 更新Anadroid SDK Tooks之后,Eclipse提示No update were found
  8. Android(安卓)更改 Toast 的默认位置及自定义Toast
  9. 更新Anadroid SDK Tooks之后,Eclipse提示No update were found

随机推荐

  1. Ubuntu 9.04:Pecl扩展名下载但不安装
  2. 跟踪PHP中的登录用户
  3. php连接mssql两种方法(com & pdo)
  4. 本机PHP函数将授予我直接访问字符串部分
  5. php多进程处理
  6. 基于MySQL查询的Laravel路由
  7. 【实战】如何通过html+css+mysql+php来快
  8. 在使用PHP编程时,使用存储过程还是硬编码S
  9. 如何在php / mysql中使用事务
  10. Zend Studio-8.0.0中文汉化教程及入门教