android 弹出式悬浮窗

本文介绍了一种通过WindowManager实现在Android应用中创建一个可跟随手指滑动的弹出视图的方法。该视图能够在点击时展开并显示更多内容,在再次点击时收起。文章详细解释了其实现思路和技术细节,并提供了一个示例代码。

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

1.最近做项目有一个弹出框的需求,要求是一个跟随手指滑动的view,点击就弹出一个View,再点击就收缩起来。在网上找资料,发现没有现成的,于是只有自己找思路,自己动手了。

2.思路:使用WindowManager的addView方法添加一个View,设置onTouch事件(onTouch事件会有很多坑),View中设置OnClick事件,监听并再View旁边再动态添加一个我姑且叫它springview。再点击的时候如果这个springView存在就移除,这样就实现了点击时的弹出跟收缩springView的目的,另外你还可以为这个springview弹出时设置动画,当然这个动画也会有很多坑。如果大家在使用中发现有很多坑可以给我留言,或者发邮件(hierophantzw@gmail.com),这些坑我就不在这里说了。下面我做了一个demo,封装了一下,大家拿到之后基本上就是可以直接用了,只需要传递一个activity的对象即可,这个对象是获取WindowManager的必要条件。


3.首先上效果图




4.部分关键代码贴出:

//封装的一个类的构造函数,需要一个activity对象

   public FloatingViewController(Activity contextActivity)
    {
        this.contextActivity = contextActivity;

        wManager = contextActivity.getWindowManager();
        wmParams = new WindowManager.LayoutParams();
        wmParams.format = PixelFormat.RGBA_8888;
        wmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE;
        wmParams.gravity = Gravity.LEFT | Gravity.TOP;


    }


//View的手指跟随

View.setOnTouchListener()

(new View.OnTouchListener()
        {


            @Override
            public boolean onTouch(View v, MotionEvent event)
            {


                switch (event.getAction())
                {
                    case MotionEvent.ACTION_DOWN:
                        xInView = event.getX();
                        yInView = event.getY();


                        xDownInScreen = event.getRawX();
                        yDownInScreen = event.getRawY() - getStatusBarHeight();
                        xInScreen = event.getRawX();
                        yInScreen = event.getRawY() - getStatusBarHeight();
                        Log.e("test", xInScreen + "down" + yInScreen);
                        break;


                    case MotionEvent.ACTION_MOVE:


                        xInScreen = event.getRawX();
                        yInScreen = event.getRawY() - getStatusBarHeight();
                        if (xInScreen == xDownInScreen && yInScreen == yDownInScreen)
                        {


                        }
                        else
                        {
                            removeBigWindow();
                            // hideView();
                        }


                        updateViewPosition();
                        break;


                    case MotionEvent.ACTION_UP:
                        xInScreen = event.getRawX();
                        yInScreen = event.getRawY() - getStatusBarHeight();


                        if (xInScreen == xDownInScreen && yInScreen == yDownInScreen)
                        {


                            Log.e("test", xInScreen + "up" + yInScreen);
                            // openBigWindow();
                            // showView();
                            return false;


                        }
                        else
                        {
                            Toast.makeText(contextActivity, "no click event", 1000).show();


                            return true;
                        }
                        // break;
                }


                return false;


            }
        });


View.setOnClickListener(new View.OnClickListener()
        {


            @Override
            public void onClick(View v)
            {


                circleButton.getLocationOnScreen(loacation);
                Log.d("test", "location-x:" + loacation[0] + "--Y:" + loacation[1]);
                int viewRight = screenWidth - (wmParams.x + wmParams.width / 2);
                int viewLeft = wmParams.x;

             //根据屏幕宽度来决定弹出窗口在左边还是右边显示的问题
                if (viewLeft > viewLength)
                {
                    openLeftBigWindow();//左边边弹出窗口
                }
                else
                {


                    if (viewRight > viewLength)
                    {
                        openRightBigWindow();//右边弹出窗口
                    }
                    else
                    {
                        xInScreen = screenWidth;
                        xInView = 60;//宽度可以自己设置
                        yInView = 60;
                        wmParams.x = (int) xInScreen;
                        wmParams.y = (int) yInScreen;
                        updateViewPosition();
                    }


                }


            }
        });
        wmParams.width = wmParams.height = (int) (60 * screenScale);

//记录每一次View移动的位置,下一次启动的时候确保View在上一次移动的那个位置
        locationPreferences = contextActivity.getPreferences(android.content.Context.MODE_PRIVATE);


        xInScreen = locationPreferences.getFloat("x", new SizeUtils(contextActivity).sysWidth);
        yInScreen = locationPreferences.getFloat("y", new SizeUtils(contextActivity).sysHeight / 2);
        xInView = 60;
        yInView = 60;
        wmParams.x = (int) xInScreen;
        wmParams.y = (int) yInScreen;


//这里在屏幕上显示了一个按钮
        wManager.addView(View, wmParams);
        updateViewPosition();


    }



//贴出一个关键函数,展示弹出窗口如何显示的代码

 protected void openLeftBigWindow()
    {


        if (wmcParams == null && childView == null)
        {
        
            wManager = contextActivity.getWindowManager();
            wmcParams = new WindowManager.LayoutParams();
            wmcParams.format = PixelFormat.RGBA_8888;
            wmcParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
            wmcParams.gravity = Gravity.LEFT | Gravity.TOP;
            wmcParams.x = (int) (loacation[0] - viewLength);
            wmcParams.y = (int) (wmParams.y);
           
            wmcParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
            wmcParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
            childView = new SpringView(contextActivity, screenScale, screenWidth, wManager, wmcParams, Orientaion.LEFT,
                    this);
            containerLayout = new LinearLayout(contextActivity);
            containerLayout.addView(childView);
            wManager.addView(containerLayout, wmcParams);


        }
        else
        {
          
            removeBigWindow();


        }


    }




demo下载链接,请点击









Android 悬浮窗菜单,可在launcher或app中使用。示例代码:@Override public void onCreate() {     super.onCreate();     mFloatMenu = new FloatMenu.Builder(this)             .floatLoader(R.drawable.yw_anim_background)             .floatLogo(R.drawable.yw_image_float_logo)             .addMenuItem(android.R.color.transparent, R.drawable.yw_menu_account, Const.MENU_ITEMS[0], android.R.color.black, this)             .addMenuItem(android.R.color.transparent, R.drawable.yw_menu_favour, Const.MENU_ITEMS[1], android.R.color.black, this)             .addMenuItem(android.R.color.transparent, R.drawable.yw_menu_fb, Const.MENU_ITEMS[2], android.R.color.black, this)             .addMenuItem(android.R.color.transparent, R.drawable.yw_menu_msg, Const.MENU_ITEMS[3], android.R.color.black, this)             .addMenuItem(android.R.color.transparent, R.drawable.yw_menu_close, Const.MENU_ITEMS[4], android.R.color.black, this)             .menuBackground(R.drawable.yw_menu_bg)             .onMenuActionListner(this)             .build();     mFloatMenu.show(); } public void showFloat() {     if (mFloatMenu != null)         mFloatMenu.show(); } public void hideFloat() {     if (mFloatMenu != null) {         mFloatMenu.hide();     } } public void destroyFloat() {     hideFloat();     if (mFloatMenu != null) {         mFloatMenu.destroy();     }     mFloatMenu = null; }  private void showRed() {     if (!hasNewMsg) {         mFloatMenu.changeLogo(R.drawable.yw_image_float_logo, R.drawable.yw_menu_msg, 3);     } else {         mFloatMenu.changeLogo(R.drawable.yw_image_float_logo_red, R.drawable.yw_menu_msg_red, 3);     } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值