android WindowManager可拖动悬浮按钮

代码地址
http://git.oschina.net/azure_sword/Sample_AS
可悬浮按钮的两种情况
1.当前页面悬浮
2.所有页面悬浮(包括系统页面)
注:第二种功能需要系统权限
android:name=”android.permission.SYSTEM_ALERT_WINDOW”

/**
* Created by zph on 2016/4/5.
*
* 当前页面悬浮按钮
*/
public class FloatView2 {
private Context c;
public FloatView2(Context c) {
this.c=c;
}

private WindowManager wm;
private View view;// 浮动按钮
/**
 * 添加悬浮View
 * @param paddingBottom 悬浮View与屏幕底部的距离
 */
public void createFloatView(int paddingBottom) {
    int w = 100;// 大小
    wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
    view = LayoutInflater.from(c).inflate(R.layout.floatview, null);
    final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
    params.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;// 所有程序窗口的“基地”窗口,其他应用程序窗口都显示在它上面。
    params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
            | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
    params.format = PixelFormat.TRANSLUCENT;// 不设置这个弹出框的透明遮罩显示为黑色
    params.width = w;
    params.height = w;
    params.gravity = Gravity.TOP | Gravity.LEFT;
    int screenWidth = c.getResources().getDisplayMetrics().widthPixels;
    int screenHeight = c.getResources().getDisplayMetrics().heightPixels;
    params.x = screenWidth - w;
    params.y = screenHeight - w - paddingBottom;
    view.setBackgroundColor(Color.TRANSPARENT);
    view.setVisibility(View.VISIBLE);
    view.setOnTouchListener(new View.OnTouchListener() {
        // 触屏监听
        float lastX, lastY;
        int oldOffsetX, oldOffsetY;
        int tag = 0;// 悬浮球 所需成员变量

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            final int action = event.getAction();
            float x = event.getX();
            float y = event.getY();
            if (tag == 0) {
                oldOffsetX = params.x; // 偏移量
                oldOffsetY = params.y; // 偏移量
            }
            if (action == MotionEvent.ACTION_DOWN) {
                lastX = x;
                lastY = y;
            } else if (action == MotionEvent.ACTION_MOVE) {
                params.x += (int) (x - lastX) / 3; // 减小偏移量,防止过度抖动
                params.y += (int) (y - lastY) / 3; // 减小偏移量,防止过度抖动
                tag = 1;
                wm.updateViewLayout(view, params);
            } else if (action == MotionEvent.ACTION_UP) {
                int newOffsetX = params.x;
                int newOffsetY = params.y;
                // 只要按钮一动位置不是很大,就认为是点击事件
                if (Math.abs(oldOffsetX - newOffsetX) <= 20
                        && Math.abs(oldOffsetY - newOffsetY) <= 20) {
                    onFloatViewClick(l);
                } else {
                    tag = 0;
                }
            }
            return true;
        }
    });
    wm.addView(view, params);
}

/**
 * 点击浮动按钮触发事件,需要override该方法
 */
private View.OnClickListener l;
public void onFloatViewClick(View.OnClickListener l) {
    this.l=l;
    Toast.makeText(c, "FLOAT", Toast.LENGTH_SHORT).show();
    view.setOnClickListener(l);
}

/**
 * 将悬浮View从WindowManager中移除,需要与createFloatView()成对出现
 */
public void removeFloatView() {
    if (wm != null && view != null) {
        wm.removeViewImmediate(view);

// wm.removeView(view);//不要调用这个,WindowLeaked
view = null;
wm = null;
}
}

/**
 * 隐藏悬浮View
 */
public void hideFloatView() {
    if (wm != null && view != null&&view.isShown()) {
        view.setVisibility(View.GONE);
    }
}
/**
 * 显示悬浮View
 */
public void showFloatView(){
    if (wm != null && view != null&&!view.isShown()) {
        view.setVisibility(View.VISIBLE);
    }
}

}

/**
* Created by zph on 2016/4/5.
*
* 全系统悬浮按钮
*/
public class FloatView extends ImageView {

private Context c;
private float mTouchX;
private float mTouchY;
private float x;
private float y;
private int startX;
private int startY;
private int imgId = R.drawable.ic_launcher;
private int controlledSpace = 20;
private int screenWidth;
private int screenHeight;
boolean isShow = false;
private OnClickListener mClickListener;

private WindowManager windowManager;

private WindowManager.LayoutParams windowManagerParams = new WindowManager.LayoutParams();

public FloatView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public FloatView(Context c) {
    super(c);
    initView(c);
}

// 初始化窗体
public void initView(Context c) {
    windowManager = (WindowManager) c.getApplicationContext()
            .getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics dm=getResources().getDisplayMetrics();
    screenWidth = dm.widthPixels;
    screenHeight = dm.heightPixels;
    this.setImageResource(imgId);
    windowManagerParams.type = WindowManager.LayoutParams.TYPE_PHONE;
    windowManagerParams.format = PixelFormat.RGBA_8888; // 背景透明
    windowManagerParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
            | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
    // 调整悬浮窗口至左上角,便于调整坐标
    windowManagerParams.gravity = Gravity.LEFT | Gravity.TOP;
    // 以屏幕左上角为原点,设置x、y初始值
    windowManagerParams.x = 0;
    windowManagerParams.y = screenHeight>>1;
    // 设置悬浮窗口长宽数据
    windowManagerParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
    windowManagerParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

}

public void setImgResource(int id) {
    imgId = id;
}

@Override
public boolean onTouchEvent(MotionEvent event) {

    x = event.getRawX();
    y = event.getRawY();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            mTouchX = event.getX();
            mTouchY = event.getY();
            startX = (int) event.getRawX();
            startY = (int) event.getRawY();
            break;

        }
        case MotionEvent.ACTION_MOVE: {
            updateViewPosition();
            break;
        }
        case MotionEvent.ACTION_UP: {

            if (Math.abs(x - startX) < controlledSpace
                    && Math.abs(y - startY) < controlledSpace) {
                if (mClickListener != null) {
                    mClickListener.onClick(this);
                }
            }

// Log.i(“tag”, “x=” + x + ” startX+” + startX + ” y=” + y
// + ” startY=” + startY);
if (x <= screenWidth / 2) {
x = 0;
} else {
x = screenWidth;
}

            updateViewPosition();

            break;
        }
    }

    return super.onTouchEvent(event);
}

// 隐藏该窗体
public void hide() {
    if (isShow) {
        windowManager.removeView(this);
        isShow = false;
    }
}
// 显示该窗体
public void show() {
    if (isShow == false) {
        windowManager.addView(this, windowManagerParams);
        isShow = true;
    }
}

@Override
public void setOnClickListener(OnClickListener l) {
    this.mClickListener = l;
}

private void updateViewPosition() {
    // 更新浮动窗口位置参数
    windowManagerParams.x = (int) (x - mTouchX);
    windowManagerParams.y = (int) (y - mTouchY);
    windowManager.updateViewLayout(this, windowManagerParams); // 刷新显示
}

}

实现代码

public class FloatingButActivity extends BaseActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_floating_but);



    floatView();

    floatView2();
}
private FloatView floatView;
private void floatView() {
    floatView = new FloatView(this);
    floatView.setImageResource(R.drawable.ic_launcher);
    floatView.show();
}
private FloatView2 floatView2;
private void floatView2() {
    floatView2 = new FloatView2(this);
    floatView2.createFloatView(100);
}


@Override
protected void onDestroy() {
    super.onDestroy();
    floatView2.removeFloatView();
    floatView.hide();
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魑魅魍魉9527

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值