From 53177035674c3c1b2a33abb021aecc2c0140b5e2 Mon Sep 17 00:00:00 2001 From: klirktag Date: Sun, 21 Jun 2026 13:36:55 +0200 Subject: [PATCH] Android: hide system bars via WindowInsetsController on API 30+ The immersive-fullscreen code hid the status and navigation bars with the deprecated View.setSystemUiVisibility() flags plus FLAG_FULLSCREEN. On Android 15+ (API 35), edge-to-edge is enforced for apps targeting SDK 35+ and those flags are ignored, so the bars never hide (e.g. on a Samsung S25). Android 14 and below still honour them, which is why older devices were unaffected. Hide/show the system bars with WindowInsetsController on API 30+ (using BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE for sticky-immersive), keeping the legacy setSystemUiVisibility() path for API < 30. The minimum supported version is unchanged. (cherry picked from commit a442367706d1bde3b29232a351e62f749559560d) --- .../main/java/org/libsdl/app/SDLActivity.java | 58 ++++++++++++++----- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index 62abfa7aa4..0ae1bcc99d 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -39,6 +39,8 @@ import android.view.Surface; import android.view.View; import android.view.ViewGroup; import android.view.Window; +import android.view.WindowInsets; +import android.view.WindowInsetsController; import android.view.WindowManager; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; @@ -952,15 +954,31 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh Window window = ((Activity) context).getWindow(); if (window != null) { if ((msg.obj instanceof Integer) && ((Integer) msg.obj != 0)) { - int flags = View.SYSTEM_UI_FLAG_FULLSCREEN | - View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE; - window.getDecorView().setSystemUiVisibility(flags); - window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + if (Build.VERSION.SDK_INT >= 30 /* Android 11 (R) */) { + // The legacy setSystemUiVisibility() flags are ignored on + // Android 15+ (API 35+), where edge-to-edge is enforced for + // apps targeting that SDK, so the status/navigation bars + // would never hide. Use WindowInsetsController instead. + window.setDecorFitsSystemWindows(false); + final WindowInsetsController controller = window.getInsetsController(); + if (controller != null) { + controller.hide(WindowInsets.Type.systemBars()); + // Sticky-immersive (replaces SYSTEM_UI_FLAG_IMMERSIVE_STICKY): + // a swipe shows the bars transiently, then they auto-hide. + controller.setSystemBarsBehavior( + WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); + } + } else { + int flags = View.SYSTEM_UI_FLAG_FULLSCREEN | + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE; + window.getDecorView().setSystemUiVisibility(flags); + window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + } SDLActivity.mFullscreenModeActive = true; } else { int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE; @@ -1799,14 +1817,22 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh private final Runnable rehideSystemUi = new Runnable() { @Override public void run() { - int flags = View.SYSTEM_UI_FLAG_FULLSCREEN | - View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE; + if (Build.VERSION.SDK_INT >= 30 /* Android 11 (R) */) { + final WindowInsetsController controller = + SDLActivity.this.getWindow().getInsetsController(); + if (controller != null) { + controller.hide(WindowInsets.Type.systemBars()); + } + } else { + int flags = View.SYSTEM_UI_FLAG_FULLSCREEN | + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE; - SDLActivity.this.getWindow().getDecorView().setSystemUiVisibility(flags); + SDLActivity.this.getWindow().getDecorView().setSystemUiVisibility(flags); + } } };