Android游戏应用内悬浮球(不需要申请权限)
16lz
2021-01-26
悬浮球踩过的坑
公司的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发送一个延时消息。完美解决。
更多相关文章
- Android开发 华为手机读取相册闪退问题
- android greenDao SQLite数据库操作工具类
- Android中的位运算的例子(一)
- Fragment封装切换
- 编写高效Android代码
- android email 邮件转发 附件不能转发问题的解决
- android中onClick事件的实现
- [Android实例] android登录Web以及登录保持,cookie管理相关
- Android(安卓)Audio代码分析=Audio Strategy