Android游戏应用内悬浮球(不需要申请权限)

悬浮球踩过的坑

公司的SDK要写一个登录界面,里面涉及到悬浮球,但是不能申请权限。起初想到的方案是利用游戏的一个Activity,通过下面代码找到容器view

View root = activity.findViewById(android.R.id.content);

然后再把悬浮球View添加进去

        View root = activity.findViewById(android.R.id.content);
        if (root instanceof FrameLayout) {
            FrameLayout content = (FrameLayout) root;
            View viewById = content.findViewById(R.id.float_ball_icon);
            if (viewById != null) {
                return;
            }
            floatView = View.inflate(gameActivity, R.layout.view_float_ball, null);
            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            ImageView floatBallIcon = floatView.findViewById(R.id.float_ball_icon);
          
            params.gravity = Gravity.START;
            params.topMargin = 100;
            ValueAnimator animator = ValueAnimator.ofFloat(0, -UIUtils.getUIUtils().getWidth(43)).setDuration(500);
            animator.setInterpolator(new LinearInterpolator());
            animator.addUpdateListener(animation -> {
                floatView.setX((Float) animation.getAnimatedValue());
                floatView.bringToFront();
            });
            animator.start();
            floatView.setLayoutParams(params);
            floatView.bringToFront();
            content.addView(floatView);
        }

整体代码就是上面的,在本地跑没什么事,但是入到游戏里面发现悬浮球移动一下就消失了,后来找到原因是游戏的surfaceView会挡住,解决方法: floatView.bringToFront(); View的这个方法,在每次移动的时候都得加这行代码,保证这个View在最前面。

但是还是会有问题,就是移动的时候有时会有穿墙的效果出现。这样放到游戏里面肯定不会

后来经过思考:第二种实现应用内悬浮球的方法popwindow,经过实验果不其然比上面方法好多了,操作还简单。

主要方法:代码如下

 public FloatPopup(Context context) {
        //记录当前悬浮按钮显示位置
        View floatView = View.inflate(gameActivity, R.layout.view_float_ball, null);
        pointView = floatView.findViewById(R.id.float_ball_point);
        pointView.setVisibility(View.GONE);
        ImageView floatBallIcon = floatView.findViewById(R.id.float_ball_icon);
        setContentView(floatView);
        setWidth(size);
        setHeight(size);
        setFocusable(false);
        setClippingEnabled(false);
        setBackgroundDrawable(new ColorDrawable(0x00000000));
        setOutsideTouchable(false);
        
        setTouchInterceptor(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                x = event.getRawX();
                y = event.getRawY();
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        downX = event.getRawX();
                        downY = event.getRawY();
                        isClickState = true;
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (Math.abs(x - downX) < clickLimitValue && Math.abs(y - downY) < clickLimitValue && isClickState) {
                            isClickState = true;
                        } else {
                            isClickState = false;
                            float offX = event.getRawX() - downX;
                            float offY = event.getRawY() - downY;

                            Log.e("floatball", "offX: " + offX + " offY:" + offY);
                            update((int) (lastX + offX), (int) (offY + lastY));
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        if (x - downX < clickLimitValue && isClickState) {
                            getContentView().performClick();
                            break;
                        }
                        if (x < screenWidth / 2.f) {
                            showX = 0;
                            showY = lastY + event.getRawY() - downY;
                        } else {
                            showX = screenWidth - size;
                            showY = lastY + event.getRawY() - downY;
                        }
                        if (showY <= 0) {
                            showY = 0;
                        } else if (showY >= screenHeight) {
                            showY = screenHeight - size;
                        }
                        update((int) showX, (int) showY);
                        lastX = showX;
                        lastY = showY;
                        v.removeCallbacks(runnable);
                        v.postDelayed(runnable, 300);

                        break;
                }
                return true;
            }
        });
    }

这之间也碰到几个问题:

1:popwindow不能移动到屏幕外 setClippingEnabled(false);加入这行代码

2:拖拽popwindows的时候,位移处理,这里就有点小技巧,就是利用初始位置+移动偏移位置就可以完美解决。

3:还有就是旋转屏幕的时候popwindow显示不出来问题,这就要监听游戏activity的生命周期,然后做相应的重建操作

4:有时游戏界面是固定方向的,但是切换字体的时候出会让activity重建,这个时候如果我们监听了activity生命周期,在onResume的时候进行重建,这时你会发现popwindwo重建不了。解决方法:利用handler发送一个延时消息。完美解决。

你可能感兴趣的:(Java,Android,android,游戏,悬浮球)