Block Android 10+ back swipe gestures for entire screen

Viewed 1516

I am trying to disable Android 10+ gesture navigation back swipes in my game (for a VERY valid reason). I need to disable swipe gestures for the whole screen.

Google's documentation is very vague about how to do this. https://developer.android.com/training/gestures/gesturenav#games

This is what I have tried. getWindow().setSystemGestureExclusionRects(exclusionRects) causes an instant crash on launch if I do it directly in my onCreate. The error I get is: java.lang.IllegalStateException: view not added.

My second attempt was setting system gesture exclusion rects inside an addOnLayoutChangeListener to the (only) view contained in my root layout so that the gesture exclusion stuff only runs once the view is good to go. For the sake of this example assume initializeForView is a function that returns a valid view. Everything works other than gestures not being blocked.

This code that I tried only blocks back swipe gestures from the lower half of the screen for some reason :(

@Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    game = new Lockjaw(this);
    AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
    RelativeLayout layout = new RelativeLayout(this);
    layout.setFitsSystemWindows(true);
    View view = initializeForView(game, config);
    layout.addView(view);
    setContentView(layout);
    view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
      @Override
      public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
                                 int oldTop, int oldRight, int oldBottom) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
          List<Rect> exclusionRects = new ArrayList();
          Rect visibleRect = new Rect();
          v.getWindowVisibleDisplayFrame(visibleRect);
          exclusionRects.add(visibleRect);
          getWindow().setSystemGestureExclusionRects(exclusionRects);
        }
      }
    });
  }
1 Answers
  1. Define this code in your Utils class.

     static List<Rect> exclusionRects = new ArrayList<>();
     public static void updateGestureExclusion(AppCompatActivity activity) {
       if (Build.VERSION.SDK_INT < 29) return;
       exclusionRects.clear();
       Rect rect = new Rect(0, 0, SystemUtil.dpToPx(activity, 16), getScreenHeight(activity));
       exclusionRects.add(rect);
    
       activity.findViewById(android.R.id.content).setSystemGestureExclusionRects(exclusionRects);
     }
    
     public static int getScreenHeight(AppCompatActivity activity) {
     DisplayMetrics displayMetrics = new DisplayMetrics();
     activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
     int height = displayMetrics.heightPixels;
     return height;
     }
    
     public static int dpToPx(Context context, int i) {
       return (int) (((float) i) * context.getResources().getDisplayMetrics().density);
     }
    
  2. Check if your layout is set in that activity where you want to exclude the edge getures and then apply this code.

     // 'content' is the root view of your layout xml.
     ViewTreeObserver treeObserver = content.getViewTreeObserver();
     treeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
         @Override
         public void onGlobalLayout() {
             content.getViewTreeObserver().removeOnGlobalLayoutListener(this);
             SystemUtil.updateGestureExclusion(MainHomeActivity.this);
         }
     });
    
  • We are adding the view width to 16dp to trigger the code when user swipe right from left edge & height to screen height to do it fully left side.
Related