Android 之浮窗篇
所谓浮窗就是悬浮在屏幕上的一个小窗口,可以拖到,点击等。像360的那个所谓的加速球就是一个经典的浮窗。我们就是要做一个这样的东西。
1、创建浮窗,同理,也是要扩展某一个东西的,我们这里选择的是linearlayout。你也可以选择view,或者imageview等等。废话不多说,我直接把代码填出来把。
public class FloatWindowView extends LinearLayout {
public FloatWindowView(Context context) {
super(context);
}
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("window");
// 此windowManagerParams变量为获取的全局变量,用以保存悬浮窗口的属性
private WindowManager.LayoutParams windowManagerParams = Constant.windowParams;
@Override
public boolean onTouchEvent(MotionEvent event) {
// 获取到状态栏的高度
Rect frame = new Rect();
getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
System.out.println("statusBarHeight:" + statusBarHeight);
// 获取相对屏幕的坐标,即以屏幕左上角为原点
x = event.getRawX();
// statusBarHeight是系统状态栏的高度
y = event.getRawY() - statusBarHeight;
Log.i("tag", "currX" + x + "====currY" + y);
switch (event.getAction()) {
// 捕获手指触摸按下动作
case MotionEvent.ACTION_DOWN:
// 获取相对View的坐标,即以此View左上角为原点
mTouchX = event.getX();
mTouchY = event.getY();
mStartX = x;
mStartY = y;
Log.i("tag", "startX" + mTouchX + "====startY" + mTouchY);
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、这里特别要注意Constant这个类,这是一个常量类
public class Constant {
/**
* 此windowManagerParams变量为获取的全局变量,用以保存悬浮窗口的属性
*/
public static final WindowManager.LayoutParams windowParams = new WindowManager.LayoutParams();
}
3、最后一步就是使用FloatWindowView这个类了。
这里需要声明三个变量。我就直接粘贴代码了。因为我把这个浮窗放在了service里面,所有你看到的是在service里面的创建浮窗的代码。
public class ScreenCaptureService extends Service {
/**
* 浮窗对象
*/
private FloatWindowView floatWindow;
/**
* 窗口管理器
*/
private WindowManager windowManager = null;
/**
* 窗口布局
*/
private WindowManager.LayoutParams windowManagerParams = null;
/**
* 内部类对象,这个就不知道是一种什么设计模式了
*/
private final IBinder baseBinder = new ScreenCaptureServiceBinder();
/**
* 内部类,这样的用法还是第一次见,他返回外部类,然后在与外部类绑定的Activity中使用外部类来操作相关的细节内容
*
* @author jeck
*
*/
public class ScreenCaptureServiceBinder extends Binder {
public ScreenCaptureService getService() {
return ScreenCaptureService.this;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 创建浮窗
crateFloatWindow();
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
return baseBinder;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
stopSelf();
}
/**
* 创建浮窗
*/
private void crateFloatWindow() {
floatWindow = new FloatWindowView(getApplicationContext());
floatWindow.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// if (isStartCapture) {
//
// // 停止录制
// isStartCapture = false;
// captureState = 0;
//
// Toast.makeText(getApplicationContext(), "录制结束",
// Toast.LENGTH_LONG).show();
//
// } else {
//
// // 启动录屏进程
// // new ScreenCaptureTask().execute();
//
// // 开始录制
// isStartCapture = true;
// captureState = 1;
//
// Toast.makeText(getApplicationContext(), "开始录屏,再次点击停止录屏",
// Toast.LENGTH_LONG).show();
//
// }
}
});
ImageView view = new ImageView(this);
// 为浮窗添加图片
view.setImageResource(R.drawable.float_window_icon);
// 这里简单的用自带的icon来做演示
floatWindow.addView(view);
windowManager = (WindowManager) getApplicationContext()
.getSystemService("window");
// 设置LayoutParams(全局变量)相关参数
windowManagerParams = Constant.windowParams;
// 设置window type
windowManagerParams.type = 2003;
// windowManagerParams.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明
// 设置Window flag
windowManagerParams.flags = 40;
windowManagerParams.format = 1;
// 调整悬浮窗口至左上角,便于调整坐标
windowManagerParams.gravity = Gravity.LEFT | Gravity.TOP;
// 以屏幕左上角为原点,设置x、y初始值
windowManagerParams.x = 100;
windowManagerParams.y = 100;
// 设置悬浮窗口长宽数据
windowManagerParams.width = 80;
windowManagerParams.height = 80;
// 显示myFloatView图像
windowManager.addView(floatWindow, windowManagerParams);
}
}
4、最后一定要记得加权限,否则会报错的哟,这一点非常重要
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />