模仿魅族flyme自带的悬浮球floatball,通过不同的触摸方式,模拟虚拟按键

觉得魅族的悬浮球做的很不错,主要是简洁方便。于是就自己实现了一下。项目源代码:FloatingBall源代码

主要是解决三个方面的问题:

  1.桌面悬浮窗的实现

  2.设置悬浮球触摸事件(拖动,点击,上下左右滑动)

  2.模拟虚拟按键(返回,home,任务面板,电源键,菜单键等)


   (一)桌面悬浮窗的实现

     通过WindowManager将自定义的悬浮球布局ballview添加到手机屏幕

     

//布局转化成要显示的viewballView = LayoutInflater.from(this).inflate(R.layout.floatball, null);wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);ballWmParams = new WindowManager.LayoutParams();//设置悬浮窗的相关参数ballWmParams.type = WindowManager.LayoutParams.TYPE_PHONE;ballWmParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;ballWmParams.gravity = Gravity.LEFT | Gravity.TOP;ballWmParams.x = MainActivity.sp.getInt("ballWmParamsX",0);ballWmParams.y = MainActivity.sp.getInt("ballWmParamsY",0);ballWmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;ballWmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;ballWmParams.format = PixelFormat.RGBA_8888;//将悬浮球view添加到屏幕wm.addView(ballView, ballWmParams);

(二)悬浮球触摸事件

    通过设置悬浮球buttton的setOnTouchListener监听触摸事件

   1.拖动悬浮球改变位置

     根据滑动的距离改变WindowManager的ballWmParams.x和ballWmParams.y实现悬浮球的拖动

   2.点击和上下左右滑动

    通过对滑动事件的x,y坐标量变化的分析,判断是点击,还是上下左右滑动

//注册触碰事件监听器floatImage.setOnTouchListener(new View.OnTouchListener() {public boolean onTouch(View v, MotionEvent event) {x = event.getX();y = event.getY();if(tag == 0){oldOffsetX = ballWmParams.x;oldOffsetY = ballWmParams.y;}switch (event.getAction()) {case MotionEvent.ACTION_DOWN:ismoving = false;mTouchStartX = (int)event.getX();mTouchStartY = (int)event.getY();break;case MotionEvent.ACTION_MOVE:ismoving = true;tag = 1;ballWmParams.x += (int) (x - mTouchStartX)/3;// 减小偏移量,防止过度抖动ballWmParams.y += (int) (y - mTouchStartY)/3;// 减小偏移量,防止过度抖动if(canmove){updateViewPosition();saveStates("ballWmParamsX", ballWmParams.x);saveStates("ballWmParamsY",ballWmParams.y);}break;case MotionEvent.ACTION_UP:mTouchStartX = mTouchStartY = 0;newOffsetX = ballWmParams.x;newOffsetY = ballWmParams.y;// 点击悬浮球if (Math.abs(oldOffsetX - newOffsetX) <= 20 && Math.abs(oldOffsetY - newOffsetY) <= 20) {onFloatBallClick();onClearOffset();}if(!canmove){//向上滑动if ((oldOffsetY - newOffsetY) - Math.abs(oldOffsetX - newOffsetX) > 20 && (oldOffsetY - newOffsetY) >20 ){onFloatBallFlipUp();}//向下滑动else if ((newOffsetY - oldOffsetY) - Math.abs(oldOffsetX - newOffsetX) > 20  && (newOffsetY - oldOffsetY) > 20 ){onFloatBallFlipDown();}//向左滑动else if ((oldOffsetX - newOffsetX) - Math.abs(oldOffsetY - newOffsetY) > 20  && (oldOffsetX - newOffsetX) > 20 ){onFloatBallFlipLeft();}//向右滑动else if((newOffsetX - oldOffsetX) - Math.abs(oldOffsetY - newOffsetY) > 20  && (newOffsetX - oldOffsetX) > 20){onFloatBallFlipRight();}onClearOffset();}tag = 0;break;}//如果拖动则返回false,否则返回trueif(ismoving == false){return false;}else{return true;}}});
 
  (三)模拟虚拟按键

      采用adb shell的input实现,反应速度慢,有延时,效果不好。

      所以采用IWindowManager和InputManager实现模拟按键事件。


 public static void simulateKey(int keyCode) {//使用KeyEvent模拟按键按下与弹起long l = SystemClock.uptimeMillis();KeyEvent localKeyEvent = new KeyEvent(l,l,KeyEvent.ACTION_DOWN,keyCode,0);KeyEvent localKeyEvent1 = new KeyEvent(l,l,KeyEvent.ACTION_UP,keyCode,0);//判断sdk版本,老版本使用IWindowManager注入按键事件,新版本使用InputManager注入按键事件//*******IWindowManager和InputManager都是隐藏类,必须在重新生成sdk中的android.jar,并包含两个类及其依赖*****if (Build.VERSION.SDK_INT < 16){try {IWindowManager.Stub.asInterface(ServiceManager.getService("window")).injectKeyEvent(localKeyEvent, true);IWindowManager.Stub.asInterface(ServiceManager.getService("window")).injectKeyEvent(localKeyEvent1, true);return;} catch (RemoteException e) {e.printStackTrace();return;}}InputManager.getInstance().injectInputEvent(localKeyEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);InputManager.getInstance().injectInputEvent(localKeyEvent1, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);}


            


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部