MyApplication.java
package com.example.windowmanagerdemo;
import android.app.Application;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
public class MyApplication extends Application{
private static WindowManager.LayoutParams params=new LayoutParams();
public WindowManager.LayoutParams getMywmParams(){
return params;
}
}
注意,application需要在注册文件里面注册
MainActivity.java
package com.example.windowmanagerdemo;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
public class MainActivity extends Activity {
WindowManager mWindowManager;
WindowManager.LayoutParams params;
FloatView mLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showView();
}
/**
* 构造并显示该悬浮窗,这里不是通过service构造的,所以仅仅在本Activity有效
* 构造内容包括权限标志flags,type,其实位置xy, 宽高,通过给view设置WindowManager.LayoutParams实现
* 通过WindowManager显示
* 所设置的View本身有点击事件
*/
private void showView(){
mLayout=new FloatView(getApplicationContext());
mLayout.setBackgroundColor(Color.GRAY);
mWindowManager=(WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
//初始化params
params=((MyApplication)getApplicationContext()).getMywmParams();
params.type=WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;//These windows are always on top of application windows.
params.format=1;
params.flags=LayoutParams.FLAG_NOT_FOCUSABLE;//不能抢占焦点
params.flags=params.flags|LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
params.flags=params.flags|LayoutParams.FLAG_LAYOUT_NO_LIMITS;//不受排版限制
params.alpha=1.0f;
params.gravity=Gravity.LEFT|Gravity.TOP;
params.x=0;
params.y=0;
params.width=140;
params.height=140;
mWindowManager.addView(mLayout, params);
//mWindowManager.updateViewLayout(mLayout, params);
}
@Override
protected void onDestroy() {
//mWindowManager.removeView(mLayout);
}
}
FloatView.java
package com.example.windowmanagerdemo;
import android.app.Application;
import android.content.Context;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
public class FloatView extends View {
private float mTouchStartX;
private float mTouchStartY;
private float x;
private float y;
private WindowManager wm = (WindowManager) getContext()
.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
private WindowManager.LayoutParams wmParams = ((MyApplication) getContext()
.getApplicationContext()).getMywmParams();
public FloatView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// 获取相对屏幕的坐标,即以屏幕左上角为原点
x = event.getRawX();
y = event.getRawY() - 60;// (不同手机所减的数值可能不一样)
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 获取view的相对坐标,以此view的左上角为原点
mTouchStartX = event.getX();
mTouchStartY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
updateViewPosition();
break;
case MotionEvent.ACTION_UP:
updateViewPosition();
mTouchStartX = mTouchStartY = 0;
break;
default:
break;
}
return true;
}
// 从这里倒着看,wmParams.x或wmParams.y是新位置的起始坐标,如果对着该图片点并不希望它会移动,但点击点的坐标和该图片所在的左上角的坐标明显不一样
// 这就需要去掉点击点相对该图片左上角的距离,也就是event.getX()或者event.getY()所得到的距离
// 由于y的由来是整个屏幕的左上角,而设置的需要是该Activity的左上角,所以y会偏大 ,偏大的距离是状态栏竖直方向的距离,本手机大概就是60
private void updateViewPosition() {
// 更新浮动窗口位置参数
wmParams.x = (int) (x - mTouchStartX);
wmParams.y = (int) (y - mTouchStartY);
wm.updateViewLayout(this, wmParams);
}
}