解决隐藏Android系统鼠标光标问题以及隐藏状态栏问题

      Android系统插上鼠标后会在屏幕显示系统光标,这套光标是无法改变的,因此在开发的过程中可能互隐藏这个光标,并且在光标碰触到手机的最上边或者最下边会触发显示状态栏,这样我们的app全屏的时候就无法获得我们app的焦点,从而我们的开发无法获取边缘地带,下面会一一的分析出来:直接上解决方法,然后在分析其他的接口的使用情况,上述情况如下图所示:

解决隐藏Android系统鼠标光标问题以及隐藏状态栏问题_第1张图片

一、解决方案

采用setOnCapturedPointerListener的方案代码如下:

public class MainActivity extends Activity
{// implements View.OnGenericMotionListener, View.OnTouchListener,View.OnSystemUiVisibilityChangeListener

    View controllerView;
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);//设置无抬头标题
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);//设置全屏

        setContentView(R.layout.activity_main);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

               controllerView = findViewById(R.id.controller_view);
//               controllerView.setOnTouchListener(this);
//               controllerView.setOnGenericMotionListener(this);

               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//只有版本大于O的才能使用这样一接口
                   // The view must be focusable for pointer capture to work.

                   controllerView.setFocusable(true);
                   controllerView.setDefaultFocusHighlightEnabled(false);
                   Log.i("MyTouchTest", "SDK_INT: ");

                   controllerView.setOnCapturedPointerListener(new View.OnCapturedPointerListener() {
                       @Override
                       public boolean onCapturedPointer(View view, MotionEvent event) {
                           Log.d("MyTouchTest", "onCapturedPointer: " + event.getAction() + " " + event.getSource());
                           return true;
                           //return handleMotionEvent(motionEvent);
                       }
                   });
               }

         Handler h = new Handler();
         h.postDelayed(new Runnable() {
             @TargetApi(Build.VERSION_CODES.O)
             @Override
             public void run() {
         	controllerView.requestPointerCapture();
             }
         }, 500);//这个线程延时很重要,不做延时或者延时时间短是无法实现view的onCapturedPointer事件监听的

    }
}

此处也可一使用监听重写的方式来实现如下所示:

public class MainActivity extends Activity implements View.OnCapturedPointerListener{
	..............
      //在onCreate内使用监听
      controllerView.setOnCapturedPointerListener(this);
      ................	                           
}

然后重写方法如下:

@Override
public boolean onCapturedPointer(View view, MotionEvent event) {
    Log.d("MyTouchTest", "onCapturedPointer: " + event.getAction() + " " + event.getSource());
    return true;
    //return handleMotionEvent(motionEvent);
}

上面的问题解决完了后还有一个问题,就是当我们的app最小化或者处于后台运行的时候,然后在切回我们的app,我们的app就会失去焦点,继而系统鼠标光标就会再次出现,因此需要override一个方法onWindowFocusChanged,重新获取焦点,代码如下:

           @Override
           public void onWindowFocusChanged(boolean hasFocus) {
               super.onWindowFocusChanged(hasFocus);

               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                   // Capture is lost when focus is lost, so it must be requested again
                   // when focus is regained.

                       // Recapture the pointer if focus was regained. On Android Q,
                       // we have to delay a bit before requesting capture because otherwise
                       // we'll hit the "requestPointerCapture called for a window that has no focus"
                       // error and it will not actually capture the cursor.
                       Handler h = new Handler();
                       h.postDelayed(new Runnable() {
                           @TargetApi(Build.VERSION_CODES.O)
                           @Override
                           public void run() {
                               controllerView.requestPointerCapture();

                           }
                       }, 500);

               }
           }

其实有了这个方法上面的onCreate内的线程延时触发可是不需要使用,但安全保障还是要使用;

此处给一个简单的xml




    
    
    
    
    
    

这个方法不仅隐藏系统鼠标光标,还不会触发状态栏的显示,从鼠标的角度看彻底隐藏了状态栏,但是通过触摸屏的下拉还是可以显示状态栏的。

关于状态栏的隐藏的方法可以参考地址:https://blog.csdn.net/bzlj2912009596/article/details/78598810

1、在AndroidManifest.xml文件中修改theme为android:theme=”@android:style/Theme.NoTitleBar.Fullscreen”
2、在setContentView方法前执行如下代码:

    requestWindowFeature(Window.FEATURE_NO_TITLE)
 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

3、通过View的setSystemUiVisibility方法
4、通过如下代码实现状态栏的隐藏和显示:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN) //隐藏状态栏
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN) //显示状态栏
推荐尝试使用第三种方法setSystemUiVisibility,其他的方法属于假隐藏;

二、其他采集鼠标的位置的接口

其他接口都无法隐藏系统光标,继而也会触发状态栏的显示,在此做个记录

//1、dispatch方法是最底层的,使用后其他方法是无法使用的

//用来采集鼠标的motion,但左键按下拖动时是无法采集到motion的,只能采集到左键的
//MotionEvent.ACTION_BUTTON_PRESS和MotionEvent.ACTION_BUTTON_RELEASE,这种状况motion只能到
//dispatchTouchEvent或者onTouch去采集,而右击和中键事件也不在这个方法内检测而是在键盘的检测方法
//内,即onKeyDown和onKeyUp内的KEYCODE_BACK和KEYCODE_MENU,但是右击滑动的motion和中键滚轮的滑动
//是在此方法内
@Override
public boolean dispatchGenericMotionEvent (MotionEvent event)/
{
        Log.i(" MyTouchTest", "dispatchGenericMotionEvent: ");
        .......................
        return false;
}

//需要注意的是方法的返回值,是false和true的区别很大,牵涉导一些事件是否能检测的到,
//如果有的事件检测不到,可以修改返回值试一试;

@Override
public boolean dispatchTouchEvent(final MotionEvent event) //触摸屏的motion采集
{
       Log.i(" MyTouchMouse", "MyTouchMouse:  action point  " + event.getAction() + " " + event.getPointerCount());
     if (event.getSource() == InputDevice.SOURCE_MOUSE) {
      ............ 
     }
     if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
      ............
     }
        ............
        return true;//不返回true,无法检测导双指按下
 }


//2、继承监听方法
//需要view的监听,必须在activity引用
public class MainActivity extends Activity implements View.OnGenericMotionListener, View.OnTouchListener

//然后在onCreate内启用监听
   controllerView.setOnTouchListener(this);
   controllerView.setOnGenericMotionListener(this);

//然后override方法

@Override
 public boolean onGenericMotionEvent(MotionEvent event) {//mouse event

    ........
   return true;

}

@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
   return false;
}

//3、还有个类似第一种方案的方法,用法和1一样


@Override
public boolean onGenericMotion(View view, MotionEvent motionEvent) {

     return false;
}

 

 

 

 

 

 

你可能感兴趣的:(Android)