1、WindowManager获取
通过WindowManager主要有
addView(
View arg0,
LayoutParams arg1)
removeView(
View arg0)
updateViewLayout(View arg0, LayoutParams arg1)三个方法
Context().getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
或到WindowManager的实例
2、WindowManager.LayoutParams配置一些参数
参数配置如下
// 设置窗口类型,一共有三种Application windows, Sub-windows, System windows
// API中以TYPE_开头的常量有23个
mWindowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
// 设置期望的bitmap格式
mWindowParams.format = PixelFormat.RGBA_8888;
mWindowParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
// 以下属性在Layout Params中常见重力、坐标,宽高
mWindowParams.gravity = Gravity.LEFT | Gravity.TOP;
//悬浮窗的初始位置(100,100)
mWindowParams.x = 100;
mWindowParams.y = 100;
设置悬浮窗的大小,下面设置宽高各为50dip
DisplayMetrics metrics=new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
mWindowParams.width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50,metrics);
mWindowParams.height =(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50,metrics);
3、通过addview方法设置悬浮显示的内容
mWindowManager.addView(imageView, mWindowParams);
到目前为止还只能显示、并不能移动下面讲实现悬浮按钮的实现
-----------------------------------不华丽的分割线---------------------------------------------------
实现移动是通过修改mWindowParams.x 和mWindowParams.y悬浮按钮的位置、然后通过updateViewLayout实现的
可以通过复写view的onTouchEvent方法(注意返回值,如果直接返回true、那么该view的onClick、onLongClick将不能被相应,最好返回父类的默认返回值)
step 1
private boolean isMoveable=false;//定义一个bool值,判断当前悬浮按钮是否可以移动,我们是只有长按以后才可以移动
在view的构造方法中
setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
isMoveable=true;
return true;
}
});
当长按后标记为可以移动
step 2
复写父类的onTouchEvent方法
@Override
public boolean onTouchEvent(MotionEvent event) {
int titleHeight = 0;
if (mListener != null) {
titleHeight = mListener.getTitleHeight();
}
// 当前值以屏幕左上角为原点
mRawX = event.getRawX();
mRawY = event.getRawY() - titleHeight;
Log.i("csl", "mRawX="+mRawX+","+"mRawY="+mRawY);
final int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// 以当前父视图左上角为原点
mStartX = event.getX();
mStartY = event.getY();
Log.i("csl", "ACTION_DOWN-->"+"mStartX="+mStartX+","+"mStartY="+mStartY);
break;
case MotionEvent.ACTION_MOVE:
if (isMoveable) {
if (moveListener!=null) {
moveListener.onMove(mRawX-mStartX, mRawY-mStartY);
}
}
break;
case MotionEvent.ACTION_UP:
if (isMoveable) {
if (moveListener!=null) {
moveListener.onMove(mRawX-mStartX, mRawY-mStartY);
}
}
isMoveable=false;
break;
}
// 消耗触摸事件
return super.onTouchEvent(event);
}
其中、getRawX(),getRawY()方法或的是当前触摸点在屏幕上的坐标 event.getX().event.getY()或得的是触摸点相对于当前View的左上角的坐标
所以当前View的坐标应该为(getRawX()-event.getX() , getRawY()-event.getY())
所以我们在手指获得的时候(DOEN/MONE/UP)的时候将当前的view的左上角坐标设置到WindowManager.LayoutParams中,然后调用updateViewLayout方法即可实现悬浮按钮的拖动
接口如下:
public interface MoveListener{
public void onMove(float x,float y);
}
private MoveListener moveListener;
public void setMoveListener(MoveListener moveListener){
this.moveListener=moveListener;
}
在Activity中实现接口并在回调方法中updateViewLayout
最后在Activity的onDestory生命周期中remove掉view