背景是公司要求做一个浮动的图片在首页。可随手指移动,抬起时自动靠边。
方法一,
1.在Application中实例WindowManager
private WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();
2.在Application中创建方法
public WindowManager.LayoutParams getMywmParams() {
return wmParams;
}
3.创建控件 GifView 是一个播放gif的控件 可以换成ImageView等等
public class FloatScanView extends GifView {
private final int statusHeight;
int sW;
int sH;
private float mTouchStartX;
private float mTouchStartY;
private float x;
private float y;
private boolean isMove = false;
private Context context;
private float topheight;//上标题栏高度
private float bottomheight;//下标题栏距顶高度
private WindowManager wm = (WindowManager) getContext()
.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
// //此wmParams变量为获取的全局变量,用以保存悬浮窗口的属性
private WindowManager.LayoutParams wmParams = ((MainApplication) getContext()
.getApplicationContext()).getMywmParams();
private float mLastX;
private float mLastY;
private float mStartX;
private float mStartY;
private long mLastTime;
private long mCurrentTime;
private Activity act;
public FloatScanView(Context context, float topheight, Activity act) {
this(context, null);
this.context = context;
this.topheight = topheight * 2 - statusHeight;
this.bottomheight = sH - topheight * 2;
this.act = act;
}
public FloatScanView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FloatScanView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
sW = wm.getDefaultDisplay().getWidth();
sH = wm.getDefaultDisplay().getHeight();
statusHeight = getStatusHeight(context);
}
/**
* 获得状态栏的高度
*
* @param context
* @return
*/
public static int getStatusHeight(Context context) {
int statusHeight = -1;
try {
Class clazz = Class.forName("com.android.internal.R$dimen");
Object object = clazz.newInstance();
int height = Integer.parseInt(clazz.getField("status_bar_height")
.get(object).toString());
statusHeight = context.getResources().getDimensionPixelSize(height);
} catch (Exception e) {
e.printStackTrace();
}
return statusHeight;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// 获取相对屏幕的坐标,即以屏幕左上角为原点
x = event.getRawX();
y = event.getRawY() - statusHeight; // statusHeight是系统状态栏的高度
// Log.i("currP", "currX" + x + "====currY" + y);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: // 捕获手指触摸按下动作
// 获取相对View的坐标,即以此View左上角为原点
mTouchStartX = event.getX();
mTouchStartY = event.getY();
mStartX = event.getRawX();
mStartY = event.getRawY();
mLastTime = System.currentTimeMillis();
// Log.i("startP", "startX" + mTouchStartX + "====startY"
// + mTouchStartY);
isMove = false;
break;
case MotionEvent.ACTION_MOVE: // 捕获手指触摸移动动作
if (topheight >= y) {
y = topheight;
} else if (bottomheight <= y) {
y = bottomheight;
}
updateViewPosition();
isMove = true;
break;
case MotionEvent.ACTION_UP: // 捕获手指触摸离开动作
mLastX = event.getRawX();
mLastY = event.getRawY();
if (y < topheight) {
y = topheight;
}
if (y > bottomheight) {
y = bottomheight;
}
// 抬起手指时让floatView紧贴屏幕左右边缘
wmParams.x = wmParams.x <= (sW / 2) ? 0 : sW;
wmParams.y = (int) (y - mTouchStartY);
wm.updateViewLayout(this, wmParams);
mCurrentTime = System.currentTimeMillis();
if (mCurrentTime - mLastTime < 800) {
if (Math.abs(mStartX - mLastX) < 10.0
&& Math.abs(mStartY - mLastY) < 10.0) {
try {
if (!MainApplication.welcomeinfo.getT_AS_IMG().equals(
"")
&& !MainApplication.welcomeinfo
.getT_AS_CONTENT().equals("")) {
// 处理点击的事件
} else {
}
} catch (Exception e) {
}
}
}
break;
}
return true;
}
private void updateViewPosition() {
// 更新浮动窗口位置参数
wmParams.x = (int) (x - mTouchStartX);
wmParams.y = (int) (y - mTouchStartY);
wm.updateViewLayout(this, wmParams); // 刷新显示
}
}
4.在主activity onCreate中使用
/*
* 浮窗区
*/
private WindowManager wm = null;
private WindowManager.LayoutParams wmParams = null;
private FloatScanView fsv = null;
private RelativeLayout main_master_appmain_headbar;
/**
* 浮窗 启动浮窗用
*
* @return
*/
@SuppressWarnings("deprecation")
private void intt() {
wm = (WindowManager) getActivity().getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE);
// wmParams = new WindowManager.LayoutParams();
sW = wm.getDefaultDisplay().getWidth();
sH = wm.getDefaultDisplay().getHeight();
System.out.println("屏幕宽度" + sW);
wmParams = ((MainApplication) getActivity().getApplication())
.getMywmParams();
wmParams.type = WindowManager.LayoutParams.TYPE_TOAST;
wmParams.format = PixelFormat.RGBA_8888;// 设置图片格式,效果为背景透明
wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;//
wmParams.gravity = Gravity.LEFT | Gravity.TOP;//
wmParams.x = wm.getDefaultDisplay().getWidth();
wmParams.y = (int) (unDisplayViewSize(main_master_appmain_headbar) * 6);//main_master_appmain_headbar我是自己的控件 y可直接赋值
wmParams.width = 150;
wmParams.height = 150;
fsv = new FloatScanView(getActivity().getApplicationContext(),
unDisplayViewSize(main_master_appmain_headbar), getActivity());
//changefuworingice();//设置浮窗样式
wm.addView(fsv, wmParams);
}
/*
* 浮窗 浮窗用 计算控件高度
*
* @param view
*
* @return
*/
public float unDisplayViewSize(View view) {
float size;
int width = View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
int height = View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
view.measure(width, height);
size = view.getMeasuredHeight();
return size;
}
应该是就这些 这种windowmanager的方式 网上很多 这个也是网上的一种。可能还有遗漏到时候自行网上补全吧。这种方式的好处是windowmanager是全局的 也就是说他会想360浮窗那样即使你退出了app仍然会悬浮在手机屏幕上,但是最大的缺点是需要手动的开启权限这个缺点相信做过的人都知道 。
第二种方法
我的需求是只需要在首页显示一个浮动窗体就可以,在这以前提下让我去每一个手机开权限 我有点受不了
所以找到另一种替代的方法
int sW;
int sH;
private float mLastX;
private float mLastY;
private float mStartX;
private float mStartY;
private long mLastTime;
private long mCurrentTime;
Button fuchuang;
private int x;
private int y;
private void intt( ) {
wm = (WindowManager) getActivity().getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE);
sW = wm.getDefaultDisplay().getWidth();
sH = wm.getDefaultDisplay().getHeight();
changefuworingice();
fuchuang.setOnTouchListener(new OnTouchListener() {
int[] temp = new int[] { 0, 0 };
float hight = unDisplayViewSize(main_master_appmain_headbar);
public boolean onTouch(View v, MotionEvent event) {
int eventaction = event.getAction();
x = (int) event.getRawX();
y = (int) event.getRawY();
switch (eventaction) {
case MotionEvent.ACTION_DOWN: // touch down so check if the
temp[0] = (int) event.getX();
temp[1] = y - v.getTop();
// 获取相对View的坐标,即以此View左上角为原点
mStartX = event.getRawX();
mStartY = event.getRawY();
mLastTime = System.currentTimeMillis();
break;
case MotionEvent.ACTION_MOVE: // touch drag with the ball
if (y < hight * 2) {
y = (int) hight * 2;
} else if (y > (sH - (hight * 1.5))) {
y = (int) (sH - (hight * 1.5));
}
v.layout(x - temp[0], y - temp[1], x + v.getWidth()
- temp[0], y - temp[1] + v.getHeight());
break;
case MotionEvent.ACTION_UP:
mLastX = event.getRawX();
mLastY = event.getRawY();
// 抬起手指时让floatView紧贴屏幕左右边缘
temp[0] = (int) mLastX;
temp[1] = y - v.getTop();
if (mLastX > sW / 2) {
v.layout(sW - v.getWidth(), y - temp[1], sW, y
- temp[1] + v.getHeight());
} else {
v.layout(0, y - temp[1], x + v.getWidth() - temp[0], y
- temp[1] + v.getHeight());
}
mCurrentTime = System.currentTimeMillis();
if (mCurrentTime - mLastTime < 800) {
if (Math.abs(mStartX - mLastX) < 10.0
&& Math.abs(mStartY - mLastY) < 10.0) {
// 处理点击的事件
}
}
//每次移动都要设置其layout,不然由于父布局可能嵌套listview,当父布局发生改变冲毁(如下拉刷新时)则移动的view会回到原来的位置
RelativeLayout.LayoutParams lpFeedback = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lpFeedback.leftMargin = v.getLeft();
lpFeedback.topMargin = v.getTop();
lpFeedback.width=v.getWidth();
lpFeedback.height=v.getHeight();
lpFeedback.setMargins(v.getLeft(), v.getTop(), 0, 0);
v.setLayoutParams(lpFeedback);
break;
}
return true;
}
});
}
RelativeLayout.LayoutParams lpFeedback = new RelativeLayout.Layout.....
这个 这可以防止页面被刷新是 浮窗回到起始位置