周五晚上加班等待测试反馈,经理在办公室,又不能特嚣张的看视频玩游戏先,于是乎就将近期做的一个悬浮框做个总结。
老规矩,先上一张效果图
这个是上周做短信时的一个需求,图片中的那个悬浮的框框就是我们今天要实现的。
整体来说,要实现这个其实还是挺简单的,原理跟Keyguard锁屏一样
- 启动一个services
- 获取WindowManager,并add一个view进去
先来看看FloatMmsService.java类
public class FloatMmsService extends Service{
private static final String TAG = "FloatMmsService";
private WindowManager wm=null;
private WindowManager.LayoutParams wmParams=null;
private FloatMmsView myFV=null;
public static ShowHandler mShowHandler;//lf
public static final String oprationKey = "sizeChange";
public static boolean AlreadyHide = true;
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
//lf add
class ShowHandler extends Handler {
static final int finish = 1;
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case finish:
stopSelf();
break;
default:
break;
}
super.handleMessage(msg);
}
}
public static void sendMsg(int msgCode) {
Message message = new Message();
message.what = msgCode;
mShowHandler.sendMessage(message);
}
//end
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
// createView();
}
@Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
createView();
mShowHandler = new ShowHandler(); //lf add
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
wm.removeView(myFV);
myFV = null;
}
public FloatMmsView getView(){
return myFV;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
if(myFV != null){
int oper = intent.getIntExtra(oprationKey, -1);
if(oper == FloatMmsView.BIGGER){
myFV.becomeBig(15);
}else if(oper == FloatMmsView.SMALLER){
myFV.becomeSmall(15);
}
}
return super.onStartCommand(intent, flags, startId);
}
private void createView(){
myFV = new FloatMmsView(getApplicationContext());
//GET WindowManager
wm = (WindowManager)getApplicationContext().getSystemService("window");
//SET LayoutParams
wmParams = myFV.getWmLayout();
wmParams.type=LayoutParams.TYPE_PHONE; //set window type
// wmParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;
wmParams.gravity = Gravity.CENTER;
wmParams.x = 0;
wmParams.y = 0;
wmParams.width = 350;
wmParams.height = 400;
wm.addView(myFV, wmParams);
AlreadyHide = false;
}
}
这个service比较简单,只是做了一件事,添加一个View到wm中。前面代码就不细讲,这里只说说关键的createView()这个方法:
private void createView(){
//初始化我们的悬浮框,我这的是FloatMmsView,具体的代码就不贴了
myFV = new FloatMmsView(getApplicationContext());
//GET WindowManager
wm =(WindowManager)getApplicationContext().getSystemService("window");
//SET LayoutParams
wmParams = myFV.getWmLayout();
wmParams.type=LayoutParams.TYPE_PHONE; //set window type
// wmParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;
//设置居中显示
wmParams.gravity = Gravity.CENTER;
wmParams.x = 0;
wmParams.y = 0;
//设置宽高,当然,这个地方也可以新增一个方法来动态改变大小
wmParams.width = 350;
wmParams.height = 400;
//最后添加到wm中就可以显示出来了
wm.addView(myFV, wmParams);
AlreadyHide = false;
}
具体实现悬浮框的时候,可能会碰到焦点问题,比如我这个短信应用,需要填写联系人,短信内容,没有焦点是弹不出软键盘的。
不需要焦点的时候,需要调用前面我们注释掉的:
wmParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;
需要焦点时,就要把这一样注释掉,并且可能需要在FloatView中做如下设置:
mEditor.setFocusable(true);
mEditor.setFocusableInTouchMode(true);
mEditor.requestFocus();
InputMethodManager inputManager = (InputMethodManager)mEditor.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.showSoftInput(mEditor, 0);
此时,悬浮框应该就可以显示出来了。那么,悬浮框显示出来之后,如何关闭呢?
在FloatView中:
private void toCloseView()
{
//设置隐藏
this.setVisibility(View.GONE);
//remove掉
this.removeView(this);
//关闭service
FloatMmsService.sendMsg(1);
}
至于悬浮框如何拖动和其他功能,就看自己悬浮框是做什么用的呢,可以自己去研究,我这就不贴代码了。
下一篇博客将会将悬浮框中的一个editor的实现,如图