项目中需要在一个service里面显示一个悬浮框,刚开始用一个对话框,但是对话框有背景,而且对话框不好控制,后来使用WindowManger实现需求。
需求是:A项目有一个service用来监听用户说的话;B项目就一个界面,基本设置的
要是实现,B项目界面启动,调用A的service来监听用户说的话,所以要在service上悬浮一个标志,代表目前是监听用户说话,还是未监听状态;并且实现悬浮框随意移动。
实现步骤:
1,先自己定义了一个布局类作为悬浮的视图;
代码:
public class ForewarnLayout extends RelativeLayout {
private float mTouchX;
private float mTouchY;
private float x;
private float y;
private float mStartX;
private float mStartY;
// 窗口视图
private WindowManager mWindowManager;
private WindowManager.LayoutParams mLayoutParams;
private OnClickListener mOnClickListener;
//语音图片
private ImageView voiceBtn = null;
private View mView = null;
private static int sign = ;
public ForewarnLayout(Context context) {
super(context);
WindowManager.LayoutParams myparams = new WindowManager.LayoutParams();
myparams.height = LayoutParams.WRAP_CONTENT;
myparams.width = LayoutParams.WRAP_CONTENT;
this.setLayoutParams(myparams);
// 加载布局
LayoutInflater lf = LayoutInflater.from(context);
mWindowManager = (WindowManager) context.getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE);
mLayoutParams = new WindowManager.LayoutParams();
mView = lf.inflate(R.layout.forewarn_layout, null);
this.addView(mView, myparams);
voiceBtn = (ImageView) findViewById(R.id.serviceVoiceBtn);
}
/**
* tounch事件
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
// 获取到状态栏的高度
Rect frame = new Rect();
getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
System.out.println("statusBarHeight:" + statusBarHeight);
// 获取相对屏幕的坐标,即以屏幕左上角为原点
x = event.getRawX();
y = event.getRawY() - statusBarHeight; // 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 = ;
if ((x - mStartX) < && (y - mStartY) < ) {
// 设置监听
if (mOnClickListener != null) {
mOnClickListener.onClick(this);
}
}
break;
}
return true;
}
// 更新浮动窗口位置参数
private void updateViewPosition() {
mLayoutParams.x = (int) (x - mTouchX);
mLayoutParams.y = (int) (y - mTouchY);
mWindowManager.updateViewLayout(this, mLayoutParams); // 刷新显示
}
// 获取界面布局参数对象
public WindowManager.LayoutParams getLayoutParams() {
return mLayoutParams;
}
// 设置界面布局参数
public void setWmParams(WindowManager.LayoutParams layoutParams) {
mLayoutParams = layoutParams;
}
// 界面点击事件监听
@Override
public void setOnClickListener(OnClickListener listener) {
mOnClickListener = listener;
}
/**
* 设置语音浮动按钮状态
*
* @param type
*/
public void setVoiceBtnType(int type) {
// 录音
if (type == ) {
voiceBtn.setImageResource(R.drawable.voice_bar_click_ok_pressed);
// 暂停录音
} else if (type == ) {
voiceBtn.setImageResource(R.drawable.voice_bar_click_normal);
}
}
}
2,service里面写了一个创建悬浮视图的方法
private WindowManager mwWindowManager = null;
private ForewarnLayout mForewarnLayout;
/**
* 浮动框视图
*/
private void createForewarnLayout() {
mForewarnLayout = new ForewarnLayout(getApplicationContext());
// 浮动视图点击事件
mForewarnLayout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
}
});
// 获取window管理对象
mwWindowManager = (WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE);
// 设置布局参数
LayoutParams forewarnLayoutParams = mForewarnLayout.getLayoutParams();
forewarnLayoutParams.type = LayoutParams.TYPE_PHONE; // 设置window TYPE
forewarnLayoutParams.format = PixelFormat.RGBA_8888; // 设置图片格式,效果位背景透明
// 设置Window flag
forewarnLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_NOT_FOCUSABLE;
forewarnLayoutParams.gravity = Gravity.LEFT | Gravity.TOP; //
// 调整悬浮窗口至左上角,便于调整坐标
// 以屏幕左上角为原点,设置X y初始值
forewarnLayoutParams.x = ;
forewarnLayoutParams.y = ;
// 设置悬浮窗口长宽数据
forewarnLayoutParams.width = LayoutParams.WRAP_CONTENT;
forewarnLayoutParams.height = LayoutParams.WRAP_CONTENT;
// forewarnLayoutParams.windowAnimations = R.style.anim_view;// 添加进入动画
// 添加布局视图
mwWindowManager.addView(mForewarnLayout, forewarnLayoutParams);
}
3,然后在service的onbind方法调用createForewarnLayout()方法,
service销毁需要移除视图,
// 移除浮动框
if (mwWindowManager != null) {
mwWindowManager.removeView(mForewarnLayout);
}
终结:WindowManager Android窗口管理类,可以理解为当前的屏幕,可以对视图添加,删除等处理。