Android 悬浮框实现

本文介绍了在Android中实现悬浮框的功能,通过启动服务并添加视图到WindowManager来达到效果。文章提到了焦点管理,如何在需要时切换悬浮框的可聚焦状态,并提供了关闭悬浮框的方法。此外,还预告了下一篇文章将探讨悬浮框中的编辑器实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

周五晚上加班等待测试反馈,经理在办公室,又不能特嚣张的看视频玩游戏先,于是乎就将近期做的一个悬浮框做个总结。
老规矩,先上一张效果图
这里写图片描述
这个是上周做短信时的一个需求,图片中的那个悬浮的框框就是我们今天要实现的。

整体来说,要实现这个其实还是挺简单的,原理跟Keyguard锁屏一样

  1. 启动一个services
  2. 获取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的实现,如图
这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值