android添加桌面悬浮窗

1. 添加权限

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

2. 自定义悬浮窗控件

@SuppressLint("ViewConstructor")
public class OEdOverLayView extends FrameLayout {

    public static OEdOverLayView create(Context context) {
        return new OEdOverLayView(context);
    }

    public static WindowManager.LayoutParams createLayoutParams() {

        final WindowManager.LayoutParams params =
                new WindowManager.LayoutParams(WRAP_CONTENT, WRAP_CONTENT, TYPE_TOAST, FLAG_NOT_FOCUSABLE
                        | FLAG_NOT_TOUCH_MODAL
                        | FLAG_LAYOUT_NO_LIMITS
                        | FLAG_LAYOUT_INSET_DECOR
                        | FLAG_LAYOUT_IN_SCREEN, TRANSLUCENT);
        params.gravity = Gravity.TOP | Gravity.LEFT;
        return params;
    }

    private OEdOverLayView(@NonNull Context context) {
        super(context);
        inflate(context, R.layout.widget_oed_overlay, this);
        init();
    }

3. 加载控件到桌面

 private void addOverLayView() {
        if (oEdOverLayView == null) {
            oEdOverLayView = OEdOverLayView.create(getApplicationContext());
            WindowManager windowManager = (WindowManager) getApplicationContext().getSystemService(WINDOW_SERVICE);
            windowManager.addView(oEdOverLayView, OEdOverLayView.createLayoutParams());
            oEdOverLayView.getRootLayout().setOnTouchListener(new OEdOverLayMoveListener(windowManager, oEdOverLayView));
        }
    }

4. 添加移动事件

public class OEdOverLayMoveListener implements View.OnTouchListener {
    private final WindowManager windowManager;
    private final View view;
    private WindowManager.LayoutParams params;
    private int initialX;
    private int initialY;
    private float initialTouchX;
    private float initialTouchY;


    public OEdOverLayMoveListener(WindowManager windowManager, View view) {
        this.windowManager = windowManager;
        this.view = view;
        this.params = (WindowManager.LayoutParams) view.getLayoutParams();
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //remember the initial position.
                initialX = params.x;
                initialY = params.y;
                //get the touch location
                initialTouchX = event.getRawX();
                initialTouchY = event.getRawY();
                return true; 
            case MotionEvent.ACTION_MOVE:
                //Calculate the X and Y coordinates of the view.
                params.x = initialX + (int) (event.getRawX() - initialTouchX);
                params.y = initialY + (int) (event.getRawY() - initialTouchY);
                //Update the layout with new X & Y coordinate
                windowManager.updateViewLayout(view, params);
                return true;
        }
        return true;
    }
}
// return ture 会消费掉touch事件,导致onclick无法获取事件

5. 小细节

    public static WindowManager.LayoutParams createLayoutParams() {

        final WindowManager.LayoutParams params =
                new WindowManager.LayoutParams(WRAP_CONTENT, WRAP_CONTENT, TYPE_TOAST, FLAG_NOT_FOCUSABLE
                        | FLAG_NOT_TOUCH_MODAL
                        | FLAG_LAYOUT_NO_LIMITS
                        | FLAG_LAYOUT_INSET_DECOR
                        | FLAG_LAYOUT_IN_SCREEN, TRANSLUCENT);
        params.gravity = Gravity.TOP | Gravity.LEFT;
        return params;
    }

  TYPE_TOAST 和 android.permission.SYSTEM_ALERT_WINDOW 可以在用户一旦取消悬浮窗权限时,添加悬浮窗

posted @ 2017-11-07 14:00  戴杭林  阅读(2089)  评论(1编辑  收藏  举报