android 实现自由移动的悬浮按钮
实现原理
主要是通过android中的WindowManager中的addview()把view加载进来,设置WindowManager.LayoutParams windowManagerParams的相关属性,例如x,y;在view的onTouchEvent中改变x,y从而实现悬浮按钮的自由移动
1、自定义一个类FloatView继承自ImageView
public class FloatView extends ImageView{
private float mTouchX;
private float mTouchY;
private float x;
private float y;
private float mStartX;
private float mStartY;
private OnClickListener mClickListener;
private WindowManager windowManager = (WindowManager) getContext()
.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
// 此windowManagerParams变量为获取的全局变量,用以保存悬浮窗口的属性
private WindowManager.LayoutParams windowManagerParams = ((FloatApplication) getContext()
.getApplicationContext()).getWindowParams();
public FloatView(Context context) {
super(context);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//获取到状态栏的高度
Rect frame = new Rect();
getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
// 获取相对屏幕的坐标,悬浮窗口所在的位置
x = event.getRawX();
y = event.getRawY() - statusBarHeight; // statusBarHeight是系统状态栏的高度
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: // 捕获手指触摸按下动作
// 获取相对View的坐标,即以此View左上角为原点
mTouchX = event.getX();
mTouchY = event.getY();
mStartX = x;
mStartY = y;
break;
case MotionEvent.ACTION_MOVE: // 捕获手指触摸移动动作
updateViewPosition();
break;
case MotionEvent.ACTION_UP: // 捕获手指触摸离开动作
updateViewPosition();
mTouchX = mTouchY = 0;
if ((x - mStartX) < 5 && (y - mStartY) < 5) {
if(mClickListener!=null) {
mClickListener.onClick(this);
}
}
break;
}
return 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); // 刷新显示
}
}
2、定义一个FloatApplication类继承Application,为了防止悬浮按钮超出相应的范围
public class FloatApplication extends Application {
private WindowManager.LayoutParams windowParams = new WindowManager.LayoutParams();
public WindowManager.LayoutParams getWindowParams() {
return windowParams;
}
}
3、在相应的Activity中创建悬浮按钮
protected static void createFloatView(int paddingBottom) {
floatView = new FloatView(mContext);
floatView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent ev) {
int action=ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
v.setBackgroundResource(R.drawable.scan_ss);
break;
case MotionEvent.ACTION_UP:
v.setBackgroundResource(R.drawable.scan_sss);
break;
default:
break;
}
return false;
}
});
floatView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
ATService.handler.obtainMessage(11).sendToTarget();
}
});
floatView.setImageResource(R.drawable.scan_sss); // 这里简单的用自带的icon来做演示
// 获取WindowManager
windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
int screenWidth = windowManager.getDefaultDisplay().getWidth();
int screenHeight = windowManager.getDefaultDisplay().getHeight();
// 设置LayoutParams(全局变量)相关参数
windowManagerParams = ((FloatApplication) mContext.getApplicationContext()).getWindowParams();
windowManagerParams.type = LayoutParams.TYPE_PHONE; // 设置window type,主要是让悬浮按钮以什么类型显示
windowManagerParams.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明
// 设置Window flag
windowManagerParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_NOT_FOCUSABLE;
/*
* flag的值可以为:
* LayoutParams.FLAG_NOT_TOUCH_MODAL 不影响后面的事件
* LayoutParams.FLAG_NOT_FOCUSABLE 不可聚焦
* LayoutParams.FLAG_NOT_TOUCHABLE 不可触摸
*/
// 调整悬浮窗口至左上角,便于调整坐标
windowManagerParams.gravity = Gravity.LEFT | Gravity.TOP;
// 以屏幕左上角为原点,设置x、y初始值 ,即控制悬浮按钮的初始位置
windowManagerParams.x = screenWidth;
windowManagerParams.y = screenHeight/2;
// 设置悬浮窗口长宽数据
windowManagerParams.width = LayoutParams.WRAP_CONTENT;
windowManagerParams.height = LayoutParams.WRAP_CONTENT;
// 显示myFloatView图像
windowManager.addView(floatView, windowManagerParams);
isFolat=true;
}
注意 最后比忘记了在AndroidManifest.xml添加相应的权限
//修改application的android:name属性 就是把之前定义的FloatApplication,前面则是FloatApplication所在的包名
android:name="com.scpark.floatwindow.FloatApplication"
android:label="@string/application_label" >
4、自由移动悬浮按钮的打开和关闭的代码
createFloatView(100);//创建
windowManager.removeView(floatView);//关闭悬浮按钮
希望对各位有所帮助,若有不对的地方,欢迎指证,谢谢。