20
20
import androidx .annotation .NonNull ;
21
21
import androidx .annotation .Nullable ;
22
22
import androidx .annotation .VisibleForTesting ;
23
+ import androidx .core .view .WindowCompat ;
24
+ import androidx .core .view .WindowInsetsCompat ;
23
25
import androidx .core .view .WindowInsetsControllerCompat ;
24
26
import io .flutter .Log ;
25
27
import io .flutter .embedding .engine .systemchannels .PlatformChannel ;
28
30
29
31
/** Android implementation of the platform plugin. */
30
32
public class PlatformPlugin {
31
- public static final int DEFAULT_SYSTEM_UI =
32
- View .SYSTEM_UI_FLAG_LAYOUT_STABLE | View .SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN ;
33
33
34
34
private final Activity activity ;
35
35
private final PlatformChannel platformChannel ;
36
36
private final PlatformPluginDelegate platformPluginDelegate ;
37
37
private PlatformChannel .SystemChromeStyle currentTheme ;
38
- private int mEnabledOverlays ;
38
+ private PlatformChannel .SystemUiMode currentSystemUiMode ;
39
+ private List <PlatformChannel .SystemUiOverlay > currentOverlays ;
39
40
private static final String TAG = "PlatformPlugin" ;
40
41
41
42
/**
@@ -141,7 +142,7 @@ public PlatformPlugin(
141
142
this .platformChannel .setPlatformMessageHandler (mPlatformMessageHandler );
142
143
this .platformPluginDelegate = delegate ;
143
144
144
- mEnabledOverlays = DEFAULT_SYSTEM_UI ;
145
+ currentSystemUiMode = PlatformChannel . SystemUiMode . EDGE_TO_EDGE ;
145
146
}
146
147
147
148
/**
@@ -240,105 +241,98 @@ public void onSystemUiVisibilityChange(int visibility) {
240
241
private void setSystemChromeEnabledSystemUIMode (PlatformChannel .SystemUiMode systemUiMode ) {
241
242
int enabledOverlays ;
242
243
243
- if (systemUiMode == PlatformChannel .SystemUiMode .LEAN_BACK
244
- && Build .VERSION .SDK_INT >= Build .VERSION_CODES .JELLY_BEAN ) {
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 ) {
245
250
// LEAN BACK
246
- // Available starting at SDK 16
251
+ // Available starting at SDK 20, due to the backwards compatibility provided by the
252
+ // WindowInsetsControllerCompat class for setting the behavior of system bars.
247
253
// Should not show overlays, tap to reveal overlays, needs onChange callback
248
254
// When the overlays come in on tap, the app does not receive the gesture and does not know
249
255
// the system overlay has changed. The overlays cannot be dismissed, so adding the callback
250
256
// support will allow users to restore the system ui and dismiss the overlays.
251
257
// Not compatible with top/bottom overlays enabled.
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 ) {
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 ) {
260
263
// IMMERSIVE
261
- // Available starting at 19
264
+ // Available starting at SDK 20, due to the backwards compatibility provided by the
265
+ // WindowInsetsControllerCompat class for setting the behavior of system bars.
262
266
// Should not show overlays, swipe from edges to reveal overlays, needs onChange callback
263
267
// When the overlays come in on swipe, the app does not receive the gesture and does not know
264
268
// the system overlay has changed. The overlays cannot be dismissed, so adding callback
265
269
// support will allow users to restore the system ui and dismiss the overlays.
266
270
// Not compatible with top/bottom overlays enabled.
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 ) {
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 ) {
276
276
// STICKY IMMERSIVE
277
- // Available starting at 19
277
+ // Available starting at SDK 20, due to the backwards compatibility provided by the
278
+ // WindowInsetsControllerCompat class for setting the behavior of system bars.
278
279
// Should not show overlays, swipe from edges to reveal overlays. The app will also receive
279
280
// the swipe gesture. The overlays cannot be dismissed, so adding callback support will
280
281
// allow users to restore the system ui and dismiss the overlays.
281
282
// Not compatible with top/bottom overlays enabled.
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 ;
283
+ windowInsetsControllerCompat .setSystemBarsBehavior (
284
+ WindowInsetsControllerCompat .BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE );
285
+ windowInsetsControllerCompat .hide (WindowInsetsCompat .Type .systemBars ());
286
+ WindowCompat .setDecorFitsSystemWindows (window , false );
289
287
} else if (systemUiMode == PlatformChannel .SystemUiMode .EDGE_TO_EDGE
290
288
&& Build .VERSION .SDK_INT >= 29 ) {
291
289
// EDGE TO EDGE
292
- // Available starting at 29
293
- // SDK 29 and up will apply a translucent body scrim behind 2/3 button navigation bars
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
294
293
// to ensure contrast with buttons on the nav and status bars, unless the contrast is not
295
294
// enforced in the overlay styling.
296
- enabledOverlays =
297
- View .SYSTEM_UI_FLAG_LAYOUT_STABLE
298
- | View .SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
299
- | View .SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN ;
295
+ WindowCompat .setDecorFitsSystemWindows (window , false );
300
296
} else {
301
297
// When none of the conditions are matched, return without updating the system UI overlays.
302
298
return ;
303
299
}
304
-
305
- mEnabledOverlays = enabledOverlays ;
306
- updateSystemUiOverlays ();
300
+ currentSystemUiMode = systemUiMode ;
307
301
}
308
302
309
303
private void setSystemChromeEnabledSystemUIOverlays (
310
304
List <PlatformChannel .SystemUiOverlay > overlaysToShow ) {
305
+ Window window = activity .getWindow ();
306
+ View view = window .getDecorView ();
307
+ WindowInsetsControllerCompat windowInsetsControllerCompat =
308
+ new WindowInsetsControllerCompat (window , view );
309
+
311
310
// Start by assuming we want to hide all system overlays (like an immersive
312
311
// game).
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 ;
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 );
324
321
}
325
322
326
323
// Re-add any desired system overlays.
327
324
for (int i = 0 ; i < overlaysToShow .size (); ++i ) {
328
325
PlatformChannel .SystemUiOverlay overlayToShow = overlaysToShow .get (i );
329
326
switch (overlayToShow ) {
330
327
case TOP_OVERLAYS :
331
- enabledOverlays &= ~ View . SYSTEM_UI_FLAG_FULLSCREEN ;
328
+ windowInsetsControllerCompat . show ( WindowInsetsCompat . Type . statusBars ()) ;
332
329
break ;
333
330
case BOTTOM_OVERLAYS :
334
- enabledOverlays &= ~View .SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION ;
335
- enabledOverlays &= ~View .SYSTEM_UI_FLAG_HIDE_NAVIGATION ;
331
+ windowInsetsControllerCompat .show (WindowInsetsCompat .Type .navigationBars ());
336
332
break ;
337
333
}
338
334
}
339
-
340
- mEnabledOverlays = enabledOverlays ;
341
- updateSystemUiOverlays ();
335
+ currentOverlays = overlaysToShow ;
342
336
}
343
337
344
338
/**
@@ -350,8 +344,11 @@ private void setSystemChromeEnabledSystemUIOverlays(
350
344
* PlatformPlugin}.
351
345
*/
352
346
public void updateSystemUiOverlays () {
353
- activity .getWindow ().getDecorView ().setSystemUiVisibility (mEnabledOverlays );
354
- if (currentTheme != null ) {
347
+ setSystemChromeEnabledSystemUIMode (currentSystemUiMode );
348
+
349
+ if (currentOverlays != null ) {
350
+ setSystemChromeEnabledSystemUIOverlays (currentOverlays );
351
+ } else if (currentTheme != null ) {
355
352
setSystemChromeSystemUIOverlayStyle (currentTheme );
356
353
}
357
354
}
0 commit comments