Android自定义可移动悬浮窗,WindowManager.LayoutParams一些属性介绍

效果图

thanks

WindowManager.LayoutParams详解

首先介绍一下常见的WindowManager.LayoutParams常量属性

layoutParams.flag

int类型 常量介绍
FLAGS_CHANGED 用于表示flags发生了变化
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON 当该window对用户可见的时候,允许锁屏。
FLAG_BLUR_BEHIND 让该window后所有东西都模糊(blur)
FLAG_DIM_BEHIND 让该window后所有的东西都成暗淡(dim)
FLAG_DITHER 开启抖动(dithering)
FLAG_FORCE_NOT_FULLSCREEN 恢复window非全屏显示
FLAG_FULLSCREEN 让window进行全屏显示
FLAG_KEEP_SCREEN_ON 当该window对用户可见时,让设备屏幕处于高亮(bright)状态。
FLAG_LAYOUT_IN_SCREEN 让window占满整个手机屏幕,不留任何边界(border)
FLAG_LAYOUT_NO_LIMITS window大小不再不受手机屏幕大小限制,即window可能超出屏幕之外,这时部分内容在屏幕之外
FLAG_NOT_FOCUSABLE 让window不能获得焦点,这样用户快就不能向该window发送按键事件及按钮事件
FLAG_NOT_TOUCHABLE 让该window不接受触摸屏事件
FLAG_NOT_TOUCH_MODAL 即使在该window在可获得焦点情况下,仍然把该window之外的任何event发送到该window之后的其他window.
FLAG_SECURE 当该window在进行显示的时候,不允许截屏。
FLAG_SHOW_WALLPAPER 在该window后显示系统的墙纸(wallpaper)
FLAG_SHOW_WHEN_LOCKED 当锁屏的时候,显示该window.
FLAG_TOUCHABLE_WHEN_WAKING 当手机处于睡眠状态时,如果屏幕被按下,那么该window将第一个收到到事件
FLAG_TURN_SCREEN_ON 当然window被显示的时候,系统将把它当做一个用户活动事件,以点亮手机屏幕。
FLAG_WATCH_OUTSIDE_TOUCH 如果你设置了该flag,那么在你FLAG_NOT_TOUNCH_MODAL的情况下,即使触摸屏事件发送在该window之外,其事件被发送到了后面的window,那么该window仍然将以MotionEvent.ACTION_OUTSIDE形式收到该触摸屏事件

layoutParams.type

类型 int 属性介绍
TYPE_APPLICATION 普通的应用程序window,token必须设置为Activity的token,以指出该窗口属谁
TYPE_APPLICATION_ATTACHED_DIALOG 对话框。类似于面板窗口,绘制类似于顶层窗口,而不是宿主的子窗口。
TYPE_APPLICATION_MEDIA 媒体窗口,例如视频。显示于宿主窗口下层。
TYPE_APPLICATION_PANEL 面板窗口,显示于宿主窗口上层
TYPE_APPLICATION_STARTING 用于应用程序启动时所显示的窗口。应用本身不要使用这种类型。它用于让系统显示些信息,直到应用程序可以开启自己的窗口
TYPE_APPLICATION_SUB_PANEL 应用程序窗口的子面板。显示于所有面板窗口的上层。(GUI的一般规律,越“子”越靠上)
TYPE_BASE_APPLICATION 所有程序窗口的“基地”窗口,其他应用程序窗口都显示在它上面。
TYPE_INPUT_METHOD 内部输入法窗口,显示于普通UI之上。应用程序可重新布局以免被此窗口覆盖
TYPE_INPUT_METHOD_DIALOG 内部输入法对话框,显示于当前输入法窗口之上
TYPE_KEYGUARD 锁屏窗口
TYPE_KEYGUARD_DIALOG 锁屏时显示的对话框
TYPE_PHONE 电话窗口。它用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。
TYPE_PRIORITY_PHONE 电话优先,当锁屏时显示。此窗口不能获得输入焦点,否则影响锁屏。
TYPE_SEARCH_BAR 搜索栏。只能有一个搜索栏;它位于屏幕上方。
TYPE_STATUS_BAR 状态栏类型的window。只能有一个状态栏window;它位于屏幕顶端,其他窗口都位于它下方。
TYPE_STATUS_BAR_PANEL 状态栏的滑动面板
TYPE_SYSTEM_ALERT 系统提示window,比如电池低的警告。它总是出现在应用程序窗口之上。
TYPE_SYSTEM_DIALOG 系统对话框。(例如音量调节框)
TYPE_SYSTEM_ERROR 系统内部错误提示,显示于所有内容之上
TYPE_SYSTEM_OVERLAY 系统顶层窗口。显示在其他一切内容之上。此窗口不能获得输入焦点,否则影响锁屏。
TYPE_TOAST toast类型的window
TYPE_WALLPAPER 用于墙纸的window

桌面浮窗权限申请

<usespermission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

此 权限6.0以上在清单文件注册没有效果,测试一下,就是动态申请权限也不能申请成功,只能用户手动开启,开启方法
Android自定义可移动悬浮窗,WindowManager.LayoutParams一些属性介绍_第1张图片

 if (Build.VERSION.SDK_INT >= 23) {
            if (!Settings.canDrawOverlays(this)) {
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                        Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent, 10);
            }
        }

设置弹窗

  private void showWindow() {
        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
        layoutParams.width = 200;
        layoutParams.height = 200;
        layoutParams.gravity =  Gravity.CENTER_VERTICAL;
        layoutParams.format = PixelFormat.TRANSPARENT;
        layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
        layoutParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_BLUR_BEHIND
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

        view = View.inflate(MainActivity.this, R.layout.window_view, null);
        TextView textView= (TextView) view;
        textView.setText("自定义弹窗");
        manager.addView(view, layoutParams);
        view.setOnTouchListener(new View.OnTouchListener() {//可以根据TouchView逻辑设置窗体跟着手指移动
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return false;
            }
        });

    }

移除弹窗

windowManager.removeView(view)

自定义跟着手指移动的View

package cn.evun.snakebardemo;

import android.content.Context;
import android.content.res.TypedArray;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

/**
 */

public class TouchView extends TextView {

    private int downX;
    private int downY;
    private boolean isMove;
    //屏幕密度
    private float density = getResources().getDisplayMetrics().density;

    public TouchView(Context context) {
        super(context, null);

    }

    public TouchView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TouchView);
        isMove = typedArray.getBoolean(R.styleable.TouchView_isMove, true);
        typedArray.recycle();
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //相对于控件左边缘的距离
                downX = (int) event.getRawX();
                downY = (int) event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                int moveX = (int) event.getRawX();
                int moveY = (int) event.getRawY();

                int dx = moveX - downX;
                int dy = moveY - downY;

                CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) getLayoutParams();
                layoutParams.leftMargin = layoutParams.leftMargin + (int) (dx * density);
                layoutParams.topMargin = layoutParams.topMargin + (int) (dy * density);

                setLayoutParams(layoutParams);
                requestLayout();

                downX = moveX;
                downY = moveY;

                break;
            case MotionEvent.ACTION_UP:
                break;
        }

        return isMove;
    }
}

源码传送

github

你可能感兴趣的:(android)