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 a442367706)
This commit is contained in:
klirktag
2026-06-21 13:36:55 +02:00
committed by Sam Lantinga
parent 3561f81400
commit 5317703567

View File

@@ -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);
}
}
};