Android 任何位置的可移动悬浮窗

刚好要做这块的东西,所以网上翻了下资料,百度出来的基本上都是:默认起始位置左上角,还不能改动,一改动起始位置,第二次拖动就不正常了~~

下面直接附上任意位置可拖动的源码(由于是demo写的比较乱):

package com.example.dengshaomin.repluginhost;

import android.content.Context;
import android.graphics.PixelFormat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private WindowManager wm = null;
    private WindowManager.LayoutParams wmParams = null;
    private ImageView leftbtn = null;
    private int statusBarHeight1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            //根据资源ID获取响应的尺寸值
            statusBarHeight1 = getResources().getDimensionPixelSize(resourceId);
        }
        setContentView(R.layout.activity_main);
        initFloatView();
    }

    public void textClick(View view) {
        Toast.makeText(MainActivity.this, view.getId() + "", Toast.LENGTH_SHORT).show();
    }

    private void initFloatView() {
        //应用内悬浮窗,ondestory时记得销毁悬浮窗
        /*
        wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
//        //设置LayoutParams(全局变量)相关参数
        wmParams = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_APPLICATION,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
                PixelFormat.TRANSLUCENT);
*/
        ///全局悬浮按钮,会显示在其他应用和桌面上
        //获取WindowManager
        wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
        //设置LayoutParams(全局变量)相关参数
        wmParams = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_TOAST,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
                PixelFormat.TRANSLUCENT);
        wmParams.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
        //以屏幕左上角为原点,设置x、y初始值
        wmParams.x = 0;
        wmParams.y = 0;
        //设置悬浮窗口长宽数据
        wmParams.width = 200;
        wmParams.height = 200;
        createLeftFloatView();
        leftbtn.invalidate();
    }

    private void createLeftFloatView() {
        leftbtn = new ImageView(this);
        leftbtn.setImageResource(R.mipmap.ic_launcher);
        leftbtn.setAlpha(100);
        leftbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Toast.makeText(MainActivity.this,"click",Toast.LENGTH_SHORT).show();
            }
        });
        //调整悬浮窗口
        //显示myFloatView图像
        wm.addView(leftbtn, wmParams);
        leftbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, "float", Toast.LENGTH_SHORT).show();
            }
        });
        leftbtn.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if (wm != null) {
                    wm.removeViewImmediate(leftbtn);
                }
//                Toast.makeText(MainActivity.this, "finish", Toast.LENGTH_SHORT).show();
                return true;
            }
        });
        leftbtn.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                // 当前值以屏幕左上角为原点
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        mStartX = event.getRawX();
                        mStartY = event.getRawY();
                        break;

                    case MotionEvent.ACTION_MOVE:
                        wmParams.x += event.getRawX() - mStartX;
                        wmParams.y += event.getRawY() - mStartY;
                        wm.updateViewLayout(leftbtn, wmParams);
                        mStartX = event.getRawX();
                        mStartY = event.getRawY();
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                }

                // 消耗触摸事件
                return true;

            }
        });
    }


    private float mStartX, mStartY;
}

  

项目地址: http://ol58b2pn9.bkt.clouddn.com/+%E5%AF%B9%E8%AF%9D%E6%A1%86%E6%82%AC%E6%B5%AE%E7%AA%97.zip

以上代码,只有显示及拖动悬浮框的处理,更高阶的悬浮框可以参考一下链接:

  http://www.cnblogs.com/tianzhijiexian/p/3994546.html

posted @ 2017-07-03 16:07  no-coding  阅读(7510)  评论(0编辑  收藏  举报