Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android 10 gesture navigation disable

TLDR: I need a way to disable Android 10 gesture navigation programmatically so that they don't accidentally go back when they swipe from the sides

The backstory: Android 10 introduced gesture navigation as opposed to the buttons at the bottom. So now on Android 10 devices that have it enabled, they can swipe from either side of the screen to go back and swipe from the bottom to navigate home or between apps. However, I am working on an implementation in AR and want to lock the screen to portrait but allow users to go landscape.

If a user turns their phone to landscape but the activity is locked to portrait, the back gesture navigation is now a swipe from the top which is a common way to access the status bar in a full screen app (which this one is) so users will inadvertently go back and leave the experience if they are used to android navigations.

Does anybody know how to either a) disable the gesture navigation (but then how does the user go back/to home?) for Android 10 programmatically or b) know how to just change the orientation for the gestures without needing your activity to support landscape?

like image 924
kjanderson2 Avatar asked Aug 09 '26 17:08

kjanderson2


2 Answers

Remember:

  • setSystemGestureExclusionRects() must be called in doOnLayout() for your view

My implementation:

    binding.root.apply { // changing gesture rects for root view
        
        doOnLayout {
            // updating exclusion rect
            val rects = mutableListOf<Rect>()
            rects.add(Rect(0,0,width,(150 * resources.displayMetrics.density).toInt()))
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                systemGestureExclusionRects = rects
            }
        }
        
    }
  • I excluded gestures for 150dp from the top, and for the entire width (just to test)

While @Dev4Life's answer was helpful, I had no success until visiting the documentation:

Android Docs: setSystemGestureExclusionRects

like image 148
SUR4IDE Avatar answered Aug 13 '26 05:08

SUR4IDE


It's very easy to block the gestures programmatically, but you can't do that for entire edges on both side. SO you have to decide on how much portion of the screen you want to disable the gestures?

Here is the code :

  • 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);
    }
    
  • 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 exclusion rectangle width to 16dp to fetch the back gesture which you can change according to your preferrences.

Here are some things to note :-

  • You must not block both side gestures. If you do so, it'll be the worst user experience.
  • "getScreenHeight(activity)" is the height of the rectangle, So if you want to block the gesture in left side & top half of the screen then simply replace it with getScreenHeight(activity)/2
  • 1st argument in new Rect() is 0 because we want the gestures on left sdie, If you want it right side then simply put - "getScreenWidth(activity) - SystemUtil.dpToPx(activity, 16)"

Hope this will solve your problem permanently. :)

like image 43
Dev4Life Avatar answered Aug 13 '26 06:08

Dev4Life



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!