2020import androidx .annotation .NonNull ;
2121import androidx .annotation .Nullable ;
2222import androidx .annotation .VisibleForTesting ;
23- import androidx .core .view .WindowCompat ;
24- import androidx .core .view .WindowInsetsCompat ;
2523import androidx .core .view .WindowInsetsControllerCompat ;
2624import io .flutter .Log ;
2725import io .flutter .embedding .engine .systemchannels .PlatformChannel ;
3028
3129/** Android implementation of the platform plugin. */
3230public class PlatformPlugin {
31+ public static final int DEFAULT_SYSTEM_UI =
32+ View .SYSTEM_UI_FLAG_LAYOUT_STABLE | View .SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN ;
3333
3434 private final Activity activity ;
3535 private final PlatformChannel platformChannel ;
3636 private final PlatformPluginDelegate platformPluginDelegate ;
3737 private PlatformChannel .SystemChromeStyle currentTheme ;
38- private PlatformChannel .SystemUiMode currentSystemUiMode ;
39- private List <PlatformChannel .SystemUiOverlay > currentOverlays ;
38+ private int mEnabledOverlays ;
4039 private static final String TAG = "PlatformPlugin" ;
4140
4241 /**
@@ -142,7 +141,7 @@ public PlatformPlugin(
142141 this .platformChannel .setPlatformMessageHandler (mPlatformMessageHandler );
143142 this .platformPluginDelegate = delegate ;
144143
145- currentSystemUiMode = PlatformChannel . SystemUiMode . EDGE_TO_EDGE ;
144+ mEnabledOverlays = DEFAULT_SYSTEM_UI ;
146145 }
147146
148147 /**
@@ -241,98 +240,105 @@ public void onSystemUiVisibilityChange(int visibility) {
241240 private void setSystemChromeEnabledSystemUIMode (PlatformChannel .SystemUiMode systemUiMode ) {
242241 int enabledOverlays ;
243242
244- Window window = activity .getWindow ();
245- View view = window .getDecorView ();
246- WindowInsetsControllerCompat windowInsetsControllerCompat =
247- new WindowInsetsControllerCompat (window , view );
248-
249- if (systemUiMode == PlatformChannel .SystemUiMode .LEAN_BACK ) {
243+ if (systemUiMode == PlatformChannel .SystemUiMode .LEAN_BACK
244+ && Build .VERSION .SDK_INT >= Build .VERSION_CODES .JELLY_BEAN ) {
250245 // LEAN BACK
251- // Available starting at SDK 20, due to the backwards compatibility provided by the
252- // WindowInsetsControllerCompat class for setting the behavior of system bars.
246+ // Available starting at SDK 16
253247 // Should not show overlays, tap to reveal overlays, needs onChange callback
254248 // When the overlays come in on tap, the app does not receive the gesture and does not know
255249 // the system overlay has changed. The overlays cannot be dismissed, so adding the callback
256250 // support will allow users to restore the system ui and dismiss the overlays.
257251 // Not compatible with top/bottom overlays enabled.
258- windowInsetsControllerCompat .setSystemBarsBehavior (
259- WindowInsetsControllerCompat .BEHAVIOR_SHOW_BARS_BY_TOUCH );
260- windowInsetsControllerCompat .hide (WindowInsetsCompat .Type .systemBars ());
261- WindowCompat .setDecorFitsSystemWindows (window , false );
262- } else if (systemUiMode == PlatformChannel .SystemUiMode .IMMERSIVE ) {
252+ enabledOverlays =
253+ View .SYSTEM_UI_FLAG_LAYOUT_STABLE
254+ | View .SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
255+ | View .SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
256+ | View .SYSTEM_UI_FLAG_HIDE_NAVIGATION
257+ | View .SYSTEM_UI_FLAG_FULLSCREEN ;
258+ } else if (systemUiMode == PlatformChannel .SystemUiMode .IMMERSIVE
259+ && Build .VERSION .SDK_INT >= Build .VERSION_CODES .KITKAT ) {
263260 // IMMERSIVE
264- // Available starting at SDK 20, due to the backwards compatibility provided by the
265- // WindowInsetsControllerCompat class for setting the behavior of system bars.
261+ // Available starting at 19
266262 // Should not show overlays, swipe from edges to reveal overlays, needs onChange callback
267263 // When the overlays come in on swipe, the app does not receive the gesture and does not know
268264 // the system overlay has changed. The overlays cannot be dismissed, so adding callback
269265 // support will allow users to restore the system ui and dismiss the overlays.
270266 // Not compatible with top/bottom overlays enabled.
271- windowInsetsControllerCompat .setSystemBarsBehavior (
272- WindowInsetsControllerCompat .BEHAVIOR_SHOW_BARS_BY_SWIPE );
273- windowInsetsControllerCompat .hide (WindowInsetsCompat .Type .systemBars ());
274- WindowCompat .setDecorFitsSystemWindows (window , false );
275- } else if (systemUiMode == PlatformChannel .SystemUiMode .IMMERSIVE_STICKY ) {
267+ enabledOverlays =
268+ View .SYSTEM_UI_FLAG_IMMERSIVE
269+ | View .SYSTEM_UI_FLAG_LAYOUT_STABLE
270+ | View .SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
271+ | View .SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
272+ | View .SYSTEM_UI_FLAG_HIDE_NAVIGATION
273+ | View .SYSTEM_UI_FLAG_FULLSCREEN ;
274+ } else if (systemUiMode == PlatformChannel .SystemUiMode .IMMERSIVE_STICKY
275+ && Build .VERSION .SDK_INT >= Build .VERSION_CODES .KITKAT ) {
276276 // STICKY IMMERSIVE
277- // Available starting at SDK 20, due to the backwards compatibility provided by the
278- // WindowInsetsControllerCompat class for setting the behavior of system bars.
277+ // Available starting at 19
279278 // Should not show overlays, swipe from edges to reveal overlays. The app will also receive
280279 // the swipe gesture. The overlays cannot be dismissed, so adding callback support will
281280 // allow users to restore the system ui and dismiss the overlays.
282281 // Not compatible with top/bottom overlays enabled.
283- windowInsetsControllerCompat .setSystemBarsBehavior (
284- WindowInsetsControllerCompat .BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE );
285- windowInsetsControllerCompat .hide (WindowInsetsCompat .Type .systemBars ());
286- WindowCompat .setDecorFitsSystemWindows (window , false );
282+ enabledOverlays =
283+ View .SYSTEM_UI_FLAG_IMMERSIVE_STICKY
284+ | View .SYSTEM_UI_FLAG_LAYOUT_STABLE
285+ | View .SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
286+ | View .SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
287+ | View .SYSTEM_UI_FLAG_HIDE_NAVIGATION
288+ | View .SYSTEM_UI_FLAG_FULLSCREEN ;
287289 } else if (systemUiMode == PlatformChannel .SystemUiMode .EDGE_TO_EDGE
288290 && Build .VERSION .SDK_INT >= 29 ) {
289291 // EDGE TO EDGE
290- // Available starting at SDK 29. See issue for context:
291- // https://github.com/flutter/flutter/issues/89774.
292- // Will apply a translucent body scrim behind 2/3 button navigation bars
292+ // Available starting at 29
293+ // SDK 29 and up will apply a translucent body scrim behind 2/3 button navigation bars
293294 // to ensure contrast with buttons on the nav and status bars, unless the contrast is not
294295 // enforced in the overlay styling.
295- WindowCompat .setDecorFitsSystemWindows (window , false );
296+ enabledOverlays =
297+ View .SYSTEM_UI_FLAG_LAYOUT_STABLE
298+ | View .SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
299+ | View .SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN ;
296300 } else {
297301 // When none of the conditions are matched, return without updating the system UI overlays.
298302 return ;
299303 }
300- currentSystemUiMode = systemUiMode ;
304+
305+ mEnabledOverlays = enabledOverlays ;
306+ updateSystemUiOverlays ();
301307 }
302308
303309 private void setSystemChromeEnabledSystemUIOverlays (
304310 List <PlatformChannel .SystemUiOverlay > overlaysToShow ) {
305- Window window = activity .getWindow ();
306- View view = window .getDecorView ();
307- WindowInsetsControllerCompat windowInsetsControllerCompat =
308- new WindowInsetsControllerCompat (window , view );
309-
310311 // Start by assuming we want to hide all system overlays (like an immersive
311312 // game).
312- windowInsetsControllerCompat .hide (WindowInsetsCompat .Type .systemBars ());
313- WindowCompat .setDecorFitsSystemWindows (window , false );
314-
315- // We apply sticky immersive mode if desired. Available starting at SDK 20.
316- if (overlaysToShow .size () == 0 ) {
317- currentSystemUiMode = PlatformChannel .SystemUiMode .IMMERSIVE_STICKY ;
318-
319- windowInsetsControllerCompat .setSystemBarsBehavior (
320- WindowInsetsControllerCompat .BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE );
313+ int enabledOverlays =
314+ DEFAULT_SYSTEM_UI
315+ | View .SYSTEM_UI_FLAG_FULLSCREEN
316+ | View .SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
317+ | View .SYSTEM_UI_FLAG_HIDE_NAVIGATION ;
318+
319+ // The SYSTEM_UI_FLAG_IMMERSIVE_STICKY flag was introduced in API 19, so we
320+ // apply it
321+ // if desired, and if the current Android version is 19 or greater.
322+ if (overlaysToShow .size () == 0 && Build .VERSION .SDK_INT >= Build .VERSION_CODES .KITKAT ) {
323+ enabledOverlays |= View .SYSTEM_UI_FLAG_IMMERSIVE_STICKY ;
321324 }
322325
323326 // Re-add any desired system overlays.
324327 for (int i = 0 ; i < overlaysToShow .size (); ++i ) {
325328 PlatformChannel .SystemUiOverlay overlayToShow = overlaysToShow .get (i );
326329 switch (overlayToShow ) {
327330 case TOP_OVERLAYS :
328- windowInsetsControllerCompat . show ( WindowInsetsCompat . Type . statusBars ()) ;
331+ enabledOverlays &= ~ View . SYSTEM_UI_FLAG_FULLSCREEN ;
329332 break ;
330333 case BOTTOM_OVERLAYS :
331- windowInsetsControllerCompat .show (WindowInsetsCompat .Type .navigationBars ());
334+ enabledOverlays &= ~View .SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION ;
335+ enabledOverlays &= ~View .SYSTEM_UI_FLAG_HIDE_NAVIGATION ;
332336 break ;
333337 }
334338 }
335- currentOverlays = overlaysToShow ;
339+
340+ mEnabledOverlays = enabledOverlays ;
341+ updateSystemUiOverlays ();
336342 }
337343
338344 /**
@@ -344,11 +350,8 @@ private void setSystemChromeEnabledSystemUIOverlays(
344350 * PlatformPlugin}.
345351 */
346352 public void updateSystemUiOverlays () {
347- setSystemChromeEnabledSystemUIMode (currentSystemUiMode );
348-
349- if (currentOverlays != null ) {
350- setSystemChromeEnabledSystemUIOverlays (currentOverlays );
351- } else if (currentTheme != null ) {
353+ activity .getWindow ().getDecorView ().setSystemUiVisibility (mEnabledOverlays );
354+ if (currentTheme != null ) {
352355 setSystemChromeSystemUIOverlayStyle (currentTheme );
353356 }
354357 }
0 commit comments