From 51b799bd2ee096f3098ed46b1c1238af727bc299 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Wed, 21 Apr 2021 16:06:24 -0500 Subject: [PATCH 01/28] Experimenting --- .../plugin/platform/PlatformPlugin.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 2140ce39f7a78..30740e51073ec 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -14,6 +14,7 @@ import android.view.SoundEffectConstants; import android.view.View; import android.view.Window; +import android.view.WindowInsets; import android.view.WindowManager; import androidx.activity.OnBackPressedDispatcherOwner; import androidx.annotation.NonNull; @@ -235,6 +236,13 @@ private void setSystemChromeEnabledSystemUIOverlays( } } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + System.out.println("how about this"); + // THIS WORKS + Window window = activity.getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + } + mEnabledOverlays = enabledOverlays; updateSystemUiOverlays(); } @@ -280,6 +288,7 @@ private void setSystemChromeSystemUIOverlayStyle( } } if (systemChromeStyle.systemNavigationBarColor != null) { + System.out.println("Setting navigationBarColor"); window.setNavigationBarColor(systemChromeStyle.systemNavigationBarColor); } } @@ -297,6 +306,7 @@ private void setSystemChromeSystemUIOverlayStyle( } } if (systemChromeStyle.statusBarColor != null) { + System.out.println("Setting statusBarColor"); window.setStatusBarColor(systemChromeStyle.statusBarColor); } } @@ -305,6 +315,20 @@ private void setSystemChromeSystemUIOverlayStyle( window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); window.setNavigationBarDividerColor(systemChromeStyle.systemNavigationBarDividerColor); } + + // Consume insets +// System.out.println("Setting up consuming insets"); +// view.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() { +// @Override +// public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { +// // 1. Move views on top edge down by insets.getSystemWindowInsetTop() +// // 2. Move views on bottom edge up by insets.getSystemWindowInsetBottom() +// // 3. Also check getSystemWindowInsetLeft/Right(), such as for landscape +// // orientations +// return insets.consumeSystemWindowInsets(); +// } +// }); + view.setSystemUiVisibility(flags); currentTheme = systemChromeStyle; } From fa046cea7e53f766e62d238adf84e12fe1e83b60 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Thu, 22 Apr 2021 16:15:29 -0500 Subject: [PATCH 02/28] skeleton, needs callbacks --- .../plugin/platform/PlatformPlugin.java | 210 +++++++++++------- 1 file changed, 131 insertions(+), 79 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 30740e51073ec..0c5d3bb9cd3bf 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -14,7 +14,6 @@ import android.view.SoundEffectConstants; import android.view.View; import android.view.Window; -import android.view.WindowInsets; import android.view.WindowManager; import androidx.activity.OnBackPressedDispatcherOwner; import androidx.annotation.NonNull; @@ -207,41 +206,93 @@ private void setSystemChromeApplicationSwitcherDescription( private void setSystemChromeEnabledSystemUIOverlays( List overlaysToShow) { - // Start by assuming we want to hide all system overlays (like an immersive - // game). + // LEAN BACK + // Available starting at 16 + // Should not show overlays, tap to reveal overlays, needs onChange callback + // When the overlays come in on tap, the app does not recieve the gesture and does not know the system overlay + // has changed. The overlays cannot be dismissed, so adding the callback support will allow users to restore + // the system ui and dismiss the overlays. + // Not compatible with top/bottom overlays enabled. + // + // View.SYSTEM_UI_FLAG_LAYOUT_STABLE + // | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + // | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + // | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + // | View.SYSTEM_UI_FLAG_FULLSCREEN; + + // IMMERSIVE + // Available starting at 19 + // Should not show overlays, swipe from edges to revela overlays, needs onChange callback + // When the overlays come in on swipe, the app does not receive the gesture and does not know the system overlay + // has changed. The overlays cannot be dismissed, so adding callback support will allow users to restore the + // system ui and dismiss the overlays. + // Not compatible with top/bottom overlays enabled. + // + // View.SYSTEM_UI_FLAG_IMMERSIVE + // | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + // | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + // | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + // | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + // | View.SYSTEM_UI_FLAG_FULLSCREEN; + + // STICKY IMMERSIVE + // Available starting at 19 + // Should not show overlays, swipe from edges to reveal overlays. The app will also receive the swipe gesture. + // The overlays cannot be dismissed, so adding callback support will allow users to restore the + // system ui and dismiss the overlays. + // Not compatible with top/bottom overlays enabled. + // + // View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + // | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + // | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + // | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + // | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + // | View.SYSTEM_UI_FLAG_FULLSCREEN; + + // EDGE TO EDGE + // Available starting at 16 + // SDK 29 and up will apply a translucent body scrim behind 2/3 button navigation bars to ensure contrast with + // buttons on the nav bar. + // SDK 28 and lower will support a transparent 2/3 button navigation bar. + // Overlays should be included and not removed. + // View.SYSTEM_UI_FLAG_LAYOUT_STABLE + // | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + // | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + + System.out.println("edge to edge"); int enabledOverlays = - DEFAULT_SYSTEM_UI - | View.SYSTEM_UI_FLAG_FULLSCREEN + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + + // MANUAL + // Use original implementation for backwards compatibility + // int enabledOverlays = + // DEFAULT_SYSTEM_UI + // | View.SYSTEM_UI_FLAG_FULLSCREEN + // | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + // | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + // // The SYSTEM_UI_FLAG_IMMERSIVE_STICKY flag was introduced in API 19, so we // apply it // if desired, and if the current Android version is 19 or greater. - if (overlaysToShow.size() == 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - enabledOverlays |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; - } - - // Re-add any desired system overlays. - for (int i = 0; i < overlaysToShow.size(); ++i) { - PlatformChannel.SystemUiOverlay overlayToShow = overlaysToShow.get(i); - switch (overlayToShow) { - case TOP_OVERLAYS: - enabledOverlays &= ~View.SYSTEM_UI_FLAG_FULLSCREEN; - break; - case BOTTOM_OVERLAYS: - enabledOverlays &= ~View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; - enabledOverlays &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - break; - } - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - System.out.println("how about this"); - // THIS WORKS - Window window = activity.getWindow(); - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); - } + // if (overlaysToShow.size() == 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + // enabledOverlays |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + // } + // Apply any specified overlays + // for (int i = 0; i < overlaysToShow.size(); ++i) { + // PlatformChannel.SystemUiOverlay overlayToShow = overlaysToShow.get(i); + // switch (overlayToShow) { + // case TOP_OVERLAYS: + // enabledOverlays &= ~View.SYSTEM_UI_FLAG_FULLSCREEN; + // break; + // case BOTTOM_OVERLAYS: + // // Don;t remove this for edge to edge + // enabledOverlays &= ~View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; + // enabledOverlays &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + // break; + // } + // } mEnabledOverlays = enabledOverlays; updateSystemUiOverlays(); @@ -270,64 +321,65 @@ private void setSystemChromeSystemUIOverlayStyle( Window window = activity.getWindow(); View view = window.getDecorView(); int flags = view.getSystemUiVisibility(); - // You can change the navigation bar color (including translucent colors) - // in Android, but you can't change the color of the navigation buttons until - // Android O. - // LIGHT vs DARK effectively isn't supported until then. - // Build.VERSION_CODES.O - if (Build.VERSION.SDK_INT >= 26) { - if (systemChromeStyle.systemNavigationBarIconBrightness != null) { - switch (systemChromeStyle.systemNavigationBarIconBrightness) { - case DARK: - // View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR - flags |= 0x10; - break; - case LIGHT: - flags &= ~0x10; - break; - } - } - if (systemChromeStyle.systemNavigationBarColor != null) { - System.out.println("Setting navigationBarColor"); - window.setNavigationBarColor(systemChromeStyle.systemNavigationBarColor); - } + + // SYSTEM STATUS BAR ------------------------------------------------------------------- + // You can't change the color of the system status bar until SDK 21. + // If transparent, SDK 29 and higher may apply a translucent scrim behind the bar to ensure + // proper contrast. This can be overridden with SystemChromeStyle.systemStatusBarContrastEnforced. + if (systemChromeStyle.statusBarColor != null && Build.VERSION.SDK_INT >= 21) { + window.setStatusBarColor(systemChromeStyle.statusBarColor); } - // Build.VERSION_CODES.M - if (Build.VERSION.SDK_INT >= 23) { - if (systemChromeStyle.statusBarIconBrightness != null) { - switch (systemChromeStyle.statusBarIconBrightness) { - case DARK: - // View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR - flags |= 0x2000; - break; - case LIGHT: - flags &= ~0x2000; - break; - } + // You can't change the color of the status icons until SDK 23. + if (systemChromeStyle.statusBarIconBrightness != null && Build.VERSION.SDK_INT >= 23) { + switch (systemChromeStyle.statusBarIconBrightness) { + case DARK: + // View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR + flags |= 0x2000; + break; + case LIGHT: + flags &= ~0x2000; + break; } - if (systemChromeStyle.statusBarColor != null) { - System.out.println("Setting statusBarColor"); - window.setStatusBarColor(systemChromeStyle.statusBarColor); + } + // You can't override the enforced contrast for a transparent status bar until SDK 29. + // This overrides the translucent scrim that may be placed behind the bar on SDK 29+ to ensure + // contrast is appropriate when using full screen layout modes like Edge to Edge. +// if (systemChromeStyle.systemStatusBarContrastEnforced != null && Build.VERSION.SDK_INT >= 29) { +// window.setStatusBarContrastEnforced(systemChromeStyle.systemStatusBarContrastEnforced); +// } + + // SYSTEM NAVIGATION BAR -------------------------------------------------------------- + // You can't change the color of the system navigation bar until SDK 21. + // If transparent, SDK 29 and higher may apply a translucent scrim behind 2/3 button navigation bars to ensure + // proper contrast. This can be overridden with SystemChromeStyle.systemNavigationBarContrastEnforced. + if (systemChromeStyle.systemNavigationBarColor != null && Build.VERSION.SDK_INT >= 21) { + window.setNavigationBarColor(systemChromeStyle.systemNavigationBarColor); + } + // You can't change the color of the navigation buttons until SDK 26. + if (systemChromeStyle.systemNavigationBarIconBrightness != null && Build.VERSION.SDK_INT >= 26) { + switch (systemChromeStyle.systemNavigationBarIconBrightness) { + case DARK: + // View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR + flags |= 0x10; + break; + case LIGHT: + flags &= ~0x10; + break; } } + // You can't change the color of the navigation bar divider color until SDK 28. if (systemChromeStyle.systemNavigationBarDividerColor != null && Build.VERSION.SDK_INT >= 28) { window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); window.setNavigationBarDividerColor(systemChromeStyle.systemNavigationBarDividerColor); } - // Consume insets -// System.out.println("Setting up consuming insets"); -// view.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() { -// @Override -// public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { -// // 1. Move views on top edge down by insets.getSystemWindowInsetTop() -// // 2. Move views on bottom edge up by insets.getSystemWindowInsetBottom() -// // 3. Also check getSystemWindowInsetLeft/Right(), such as for landscape -// // orientations -// return insets.consumeSystemWindowInsets(); -// } -// }); + // You can't override the enforced contrast for a transparent navigation bar until SDK 29. + // This overrides the translucent scrim that may be placed behind 2/3 button navigation bars on SDK 29+ to ensure + // contrast is appropriate when using full screen layout modes like Edge to Edge. +// if (systemChromeStyle.systemNavigationBarContrastEnforced != null && Build.VERSION.SDK_INT >= 29) { +// window.setNavigationBarContrastEnforced(systemChromeStyle.systemNavigationBarContrastEnforced); +// } view.setSystemUiVisibility(flags); currentTheme = systemChromeStyle; From 50e324b4a8b52ea29acde4d325d6e489b1c304dc Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Thu, 22 Apr 2021 16:49:10 -0500 Subject: [PATCH 03/28] ++ --- .../plugin/platform/PlatformPlugin.java | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 0c5d3bb9cd3bf..8b7af8f606805 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -206,6 +206,14 @@ private void setSystemChromeApplicationSwitcherDescription( private void setSystemChromeEnabledSystemUIOverlays( List overlaysToShow) { + System.out.println("lean back"); + int enabledOverlays = + View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN; + // LEAN BACK // Available starting at 16 // Should not show overlays, tap to reveal overlays, needs onChange callback @@ -255,16 +263,11 @@ private void setSystemChromeEnabledSystemUIOverlays( // buttons on the nav bar. // SDK 28 and lower will support a transparent 2/3 button navigation bar. // Overlays should be included and not removed. + // View.SYSTEM_UI_FLAG_LAYOUT_STABLE // | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION // | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; - System.out.println("edge to edge"); - int enabledOverlays = - View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; - // MANUAL // Use original implementation for backwards compatibility // int enabledOverlays = @@ -287,13 +290,34 @@ private void setSystemChromeEnabledSystemUIOverlays( // enabledOverlays &= ~View.SYSTEM_UI_FLAG_FULLSCREEN; // break; // case BOTTOM_OVERLAYS: - // // Don;t remove this for edge to edge - // enabledOverlays &= ~View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; + // enabledOverlays &= ~View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; // Don't remove this for edge to edge, this is the OG bug // enabledOverlays &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; // break; // } // } + // Set up a listener to notify the framework when the system ui has changed. + View decorView = activity.getWindow().getDecorView(); + decorView.setOnSystemUiVisibilityChangeListener + (new View.OnSystemUiVisibilityChangeListener() { + @Override + public void onSystemUiVisibilityChange(int visibility) { + if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { + // The system bars are visible. Make any desired adjustments to your UI, such as + // showing the action bar or other navigational controls. + // Another common action is to set a timer to dismiss the system bars and restore + // the fullscreen mode that was perviously enabled. + // TODO(Piinks): Wire up callback to the framework + System.out.println("No longer in fullscreen"); + } else { + // The system bars are NOT visible. Make any desired adjustments to your UI, such + // as hiding the action bar or other navigational controls. + // TODO(Piinks): Wire up callback to the framework + System.out.println("Fullscreen"); + } + } + }); + mEnabledOverlays = enabledOverlays; updateSystemUiOverlays(); } From b0be4251282b1eb971a72b4e77b781268d6975e5 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Mon, 26 Apr 2021 16:47:31 -0500 Subject: [PATCH 04/28] Progress --- .../systemchannels/PlatformChannel.java | 86 ++++++- .../plugin/platform/PlatformPlugin.java | 234 ++++++++++-------- .../framework/Source/FlutterPlatformPlugin.mm | 23 ++ .../fuchsia/flutter/compilation_trace.txt | 2 + 4 files changed, 241 insertions(+), 104 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index 06833cbe2c225..88222c9c72a6d 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -313,6 +313,32 @@ private List decodeSystemUiOverlays(@NonNull JSONArray encodedS return overlays; } + /** + * Decodes an object of JSON-encoded mode to a {@link SystemUiMode}. + * + * @throws JSONException if {@code encodedSystemUiMode} does not contain expected keys and + * value types. + * @throws NoSuchFieldException if any of the given encoded mode name is invalid. + */ + @NonNull + private SystemUiMode decodeSystemUiMode(@NonNull JSONObject encodedSystemUiMode) + throws JSONException, NoSuchFieldException { + String encodedMode = encodedSystemUiMode.getString(i); + SystemUiMode mode = SystemUiMode.fromValue(encodedMode); + switch (mode) { + case LEAN_BACK: + return SystemUiMode.LEAN_BACK; + case IMMERSIVE: + return SystemUiMode.IMMERSIVE; + case IMMERSIVE_STICKY: + return SystemUiMode.IMMERSIVE_STICKY; + case EDGE_TO_EDGE: + return SystemUiMode.EDGE_TO_EDGE; + case MANUAL: + return SystemUiMode.MANUAL; + } + } + /** * Decodes a JSON-encoded {@code encodedStyle} to a {@link SystemChromeStyle}. * @@ -399,12 +425,39 @@ public interface PlatformMessageHandler { */ void showSystemOverlays(@NonNull List overlays); + /** + * The Flutter application would like the Android system to display the given {@code mode}, or manually configured + * {@code overlays}. + * + *

{@link SystemUiMode#LEAN_BACK} refers to a fullscreen experience that restores system bars upon tapping + * anywhere in the application. This tap gesture is not received by the application. + * + *

{@link SystemUiMode#IMMERSIVE} refers to a fullscreen experience that restores system bars upon swiping from + * the edge of the viewport. This swipe gesture is not recived by the application. + * + *

{@link SystemUiMode#IMMERSIVE_STICKY} refers to a fullscreen experience that restores system bars upon swiping + * from the edge of the viewport. This swipe gesture is received by the application, in contrast to + * {@link SystemUiMode#IMMERSIVE}. + * + *

{@link SystemUiMode#EDGE_TO_EDGE} refers to a layout configuration that will consume the full viewport. This + * full screen experience does not hide status bars. These status bars can be set to transparent, making the buttons + * and icons hover over the fullscreen application. + * + *

{@link SystemUiMode#MANUAL} allows for manual configuration of system status bars. These can be set with the + * given {@code overlays}. {@link SystemUiOverlay#TOP_OVERLAYS} refers to system overlays such as the status bar, + * while {@link SystemUiOverlay#BOTTOM_OVERLAYS} refers to system overlays such as the + * back/home/recents navigation on the bottom of the screen. An empty list of {@code overlays} should hide all + * system overlays. + */ + // TODO(Piinks): add callback for system Ui change + void showSystemUiMode(@NonNull SystemUiMode mode, @Nullable List overlays); + /** * The Flutter application would like to restore the visibility of system overlays to the last - * set of overlays sent via {@link #showSystemOverlays(List)}. + * set of overlays sent via {@link #showSystemOverlays(List)} or {@link #showSystemUiMode(SystemUiMode, List)}. * - *

If {@link #showSystemOverlays(List)} has yet to be called, then a default system overlay - * appearance is desired: + *

If {@link #showSystemOverlays(List)} or {@link #showSystemUiMode(SystemUiMode, List)} has yet to be called, + * then a default system overlay appearance is desired: * *

{@code View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN } */ @@ -542,6 +595,33 @@ static SystemUiOverlay fromValue(@NonNull String encodedName) throws NoSuchField } } + /** + * The set of Android system fullscreen modes as perceived by the Flutter application. + */ + public enum SystemUiMode { + LEAN_BACK("SystemUiMode.lean_back"), + IMMERSIVE("SystemUiMode.immersive"), + IMMERSIVE_STICKY("SystemUiMode.immersive_sticky"), + EDGE_TO_EDGE("SystemUiMode.edge_to_edge"), + MANUAL("SystemUiMode.manual"); + + @NonNull + static SystemUiMode fromValue(@NonNull String encodedName) throws NoSuchFieldException { + for (SystemUiMode mode : SystemUiMode.values()) { + if (mode.encodedName.equals(encodedName)) { + return mode; + } + } + throw new NoSuchFieldException("No such SystemUiMode: " + encodedName); + } + + @NonNull private String encodedName; + + SystemUiMode(@NonNull String encodedName) { + this.encodedName = encodedName; + } + } + /** * The color and label of an application that appears in Android's app switcher, AKA recents * screen. diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 8b7af8f606805..7c6709de91d4d 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -85,6 +85,11 @@ public void showSystemOverlays(@NonNull List ov setSystemChromeEnabledSystemUIOverlays(overlays); } + @Override + public void showSystemUiMode(@NonNull SystemUiMode mode, @Nullable List overlays) { + setSystemChromeEnabledSystemUIMode(mode, overlays); + } + @Override public void restoreSystemUiOverlays() { restoreSystemChromeSystemUIOverlays(); @@ -204,99 +209,89 @@ private void setSystemChromeApplicationSwitcherDescription( } } - private void setSystemChromeEnabledSystemUIOverlays( - List overlaysToShow) { - System.out.println("lean back"); + private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode systemUiMode, @Nullable List manualOverlaysToShow) { int enabledOverlays = - View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_FULLSCREEN; - - // LEAN BACK - // Available starting at 16 - // Should not show overlays, tap to reveal overlays, needs onChange callback - // When the overlays come in on tap, the app does not recieve the gesture and does not know the system overlay - // has changed. The overlays cannot be dismissed, so adding the callback support will allow users to restore - // the system ui and dismiss the overlays. - // Not compatible with top/bottom overlays enabled. - // - // View.SYSTEM_UI_FLAG_LAYOUT_STABLE - // | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - // | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - // | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - // | View.SYSTEM_UI_FLAG_FULLSCREEN; - - // IMMERSIVE - // Available starting at 19 - // Should not show overlays, swipe from edges to revela overlays, needs onChange callback - // When the overlays come in on swipe, the app does not receive the gesture and does not know the system overlay - // has changed. The overlays cannot be dismissed, so adding callback support will allow users to restore the - // system ui and dismiss the overlays. - // Not compatible with top/bottom overlays enabled. - // - // View.SYSTEM_UI_FLAG_IMMERSIVE - // | View.SYSTEM_UI_FLAG_LAYOUT_STABLE - // | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - // | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - // | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - // | View.SYSTEM_UI_FLAG_FULLSCREEN; - - // STICKY IMMERSIVE - // Available starting at 19 - // Should not show overlays, swipe from edges to reveal overlays. The app will also receive the swipe gesture. - // The overlays cannot be dismissed, so adding callback support will allow users to restore the - // system ui and dismiss the overlays. - // Not compatible with top/bottom overlays enabled. - // - // View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - // | View.SYSTEM_UI_FLAG_LAYOUT_STABLE - // | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - // | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - // | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - // | View.SYSTEM_UI_FLAG_FULLSCREEN; - - // EDGE TO EDGE - // Available starting at 16 - // SDK 29 and up will apply a translucent body scrim behind 2/3 button navigation bars to ensure contrast with - // buttons on the nav bar. - // SDK 28 and lower will support a transparent 2/3 button navigation bar. - // Overlays should be included and not removed. - - // View.SYSTEM_UI_FLAG_LAYOUT_STABLE - // | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - // | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; - - // MANUAL - // Use original implementation for backwards compatibility - // int enabledOverlays = - // DEFAULT_SYSTEM_UI - // | View.SYSTEM_UI_FLAG_FULLSCREEN - // | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - // | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - // - // The SYSTEM_UI_FLAG_IMMERSIVE_STICKY flag was introduced in API 19, so we - // apply it - // if desired, and if the current Android version is 19 or greater. - // if (overlaysToShow.size() == 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - // enabledOverlays |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; - // } - // Apply any specified overlays - // for (int i = 0; i < overlaysToShow.size(); ++i) { - // PlatformChannel.SystemUiOverlay overlayToShow = overlaysToShow.get(i); - // switch (overlayToShow) { - // case TOP_OVERLAYS: - // enabledOverlays &= ~View.SYSTEM_UI_FLAG_FULLSCREEN; - // break; - // case BOTTOM_OVERLAYS: - // enabledOverlays &= ~View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; // Don't remove this for edge to edge, this is the OG bug - // enabledOverlays &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - // break; - // } - // } + DEFAULT_SYSTEM_UI + | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + + if (systemUiMode == LEAN_BACK && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + // LEAN BACK + // Available starting at SDK 16 + // Should not show overlays, tap to reveal overlays, needs onChange callback + // When the overlays come in on tap, the app does not recieve the gesture and does not know the system overlay + // has changed. The overlays cannot be dismissed, so adding the callback support will allow users to restore + // the system ui and dismiss the overlays. + // Not compatible with top/bottom overlays enabled. + enabledOverlays = View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN; + } else if (systemUiMode == IMMERSIVE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + // IMMERSIVE + // Available starting at 19 + // Should not show overlays, swipe from edges to revela overlays, needs onChange callback + // When the overlays come in on swipe, the app does not receive the gesture and does not know the system overlay + // has changed. The overlays cannot be dismissed, so adding callback support will allow users to restore the + // system ui and dismiss the overlays. + // Not compatible with top/bottom overlays enabled. + enabledOverlays = View.SYSTEM_UI_FLAG_IMMERSIVE + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN; + } else if (systemUiMode == IMMERSIVE_STICKY && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + // STICKY IMMERSIVE + // Available starting at 19 + // Should not show overlays, swipe from edges to reveal overlays. The app will also receive the swipe gesture. + // The overlays cannot be dismissed, so adding callback support will allow users to restore the + // system ui and dismiss the overlays. + // Not compatible with top/bottom overlays enabled. + enabledOverlays = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN; + } else if (systemUiMode == EDGE_TO_EDGE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + // EDGE TO EDGE + // Available starting at 16 + // SDK 29 and up will apply a translucent body scrim behind 2/3 button navigation bars to ensure contrast with + // buttons on the nav bar. + // SDK 28 and lower will support a transparent 2/3 button navigation bar. + // Overlays should be included and not removed. + enabledOverlays = View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + } else if (systemUiMode == MANUAL) { + // MANUAL + // Use original implementation of setSystemChromeEnabledSystemUIOverlays for backwards compatibility + + // The SYSTEM_UI_FLAG_IMMERSIVE_STICKY flag was introduced in API 19, so we apply it if desired, and if the + // current Android version is 19 or greater. + if (overlaysToShow.size() == 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + enabledOverlays |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + } + // Apply any specified overlays + for (int i = 0; i < overlaysToShow.size(); ++i) { + PlatformChannel.SystemUiOverlay overlayToShow = overlaysToShow.get(i); + switch (overlayToShow) { + case TOP_OVERLAYS: + enabledOverlays &= ~View.SYSTEM_UI_FLAG_FULLSCREEN; + break; + case BOTTOM_OVERLAYS: + enabledOverlays &= ~View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; // <- This flag blocks edge to edge + enabledOverlays &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + break; + } + } + } // Set up a listener to notify the framework when the system ui has changed. + // TODO(Piinks): Document this heavily. E2E would not be a relevant use case for this callback functionality. View decorView = activity.getWindow().getDecorView(); decorView.setOnSystemUiVisibilityChangeListener (new View.OnSystemUiVisibilityChangeListener() { @@ -322,6 +317,43 @@ public void onSystemUiVisibilityChange(int visibility) { updateSystemUiOverlays(); } + // This method is deprecated, use setSystemChromeEnabledSystemUIMode instead. + @Deprecated + private void setSystemChromeEnabledSystemUIOverlays( + List overlaysToShow) { + // Start by assuming we want to hide all system overlays (like an immersive + // game). + int enabledOverlays = + DEFAULT_SYSTEM_UI + | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + + // The SYSTEM_UI_FLAG_IMMERSIVE_STICKY flag was introduced in API 19, so we + // apply it + // if desired, and if the current Android version is 19 or greater. + if (overlaysToShow.size() == 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + enabledOverlays |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + } + + // Re-add any desired system overlays. + for (int i = 0; i < overlaysToShow.size(); ++i) { + PlatformChannel.SystemUiOverlay overlayToShow = overlaysToShow.get(i); + switch (overlayToShow) { + case TOP_OVERLAYS: + enabledOverlays &= ~View.SYSTEM_UI_FLAG_FULLSCREEN; + break; + case BOTTOM_OVERLAYS: + enabledOverlays &= ~View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; + enabledOverlays &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + break; + } + } + + mEnabledOverlays = enabledOverlays; + updateSystemUiOverlays(); + } + /** * Refreshes Android's window system UI (AKA system chrome) to match Flutter's desired {@link * PlatformChannel.SystemChromeStyle}. @@ -350,11 +382,11 @@ private void setSystemChromeSystemUIOverlayStyle( // You can't change the color of the system status bar until SDK 21. // If transparent, SDK 29 and higher may apply a translucent scrim behind the bar to ensure // proper contrast. This can be overridden with SystemChromeStyle.systemStatusBarContrastEnforced. - if (systemChromeStyle.statusBarColor != null && Build.VERSION.SDK_INT >= 21) { + if (systemChromeStyle.statusBarColor != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { window.setStatusBarColor(systemChromeStyle.statusBarColor); } // You can't change the color of the status icons until SDK 23. - if (systemChromeStyle.statusBarIconBrightness != null && Build.VERSION.SDK_INT >= 23) { + if (systemChromeStyle.statusBarIconBrightness != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.MARSHMALLOW) { switch (systemChromeStyle.statusBarIconBrightness) { case DARK: // View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR @@ -368,19 +400,19 @@ private void setSystemChromeSystemUIOverlayStyle( // You can't override the enforced contrast for a transparent status bar until SDK 29. // This overrides the translucent scrim that may be placed behind the bar on SDK 29+ to ensure // contrast is appropriate when using full screen layout modes like Edge to Edge. -// if (systemChromeStyle.systemStatusBarContrastEnforced != null && Build.VERSION.SDK_INT >= 29) { -// window.setStatusBarContrastEnforced(systemChromeStyle.systemStatusBarContrastEnforced); -// } + if (systemChromeStyle.systemStatusBarContrastEnforced != null && Build.VERSION.SDK_INT >= 29) { + window.setStatusBarContrastEnforced(systemChromeStyle.systemStatusBarContrastEnforced); + } // SYSTEM NAVIGATION BAR -------------------------------------------------------------- // You can't change the color of the system navigation bar until SDK 21. // If transparent, SDK 29 and higher may apply a translucent scrim behind 2/3 button navigation bars to ensure // proper contrast. This can be overridden with SystemChromeStyle.systemNavigationBarContrastEnforced. - if (systemChromeStyle.systemNavigationBarColor != null && Build.VERSION.SDK_INT >= 21) { + if (systemChromeStyle.systemNavigationBarColor != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { window.setNavigationBarColor(systemChromeStyle.systemNavigationBarColor); } // You can't change the color of the navigation buttons until SDK 26. - if (systemChromeStyle.systemNavigationBarIconBrightness != null && Build.VERSION.SDK_INT >= 26) { + if (systemChromeStyle.systemNavigationBarIconBrightness != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.OREO) { switch (systemChromeStyle.systemNavigationBarIconBrightness) { case DARK: // View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR @@ -392,7 +424,7 @@ private void setSystemChromeSystemUIOverlayStyle( } } // You can't change the color of the navigation bar divider color until SDK 28. - if (systemChromeStyle.systemNavigationBarDividerColor != null && Build.VERSION.SDK_INT >= 28) { + if (systemChromeStyle.systemNavigationBarDividerColor != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.PIE) { window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); window.setNavigationBarDividerColor(systemChromeStyle.systemNavigationBarDividerColor); @@ -401,9 +433,9 @@ private void setSystemChromeSystemUIOverlayStyle( // You can't override the enforced contrast for a transparent navigation bar until SDK 29. // This overrides the translucent scrim that may be placed behind 2/3 button navigation bars on SDK 29+ to ensure // contrast is appropriate when using full screen layout modes like Edge to Edge. -// if (systemChromeStyle.systemNavigationBarContrastEnforced != null && Build.VERSION.SDK_INT >= 29) { -// window.setNavigationBarContrastEnforced(systemChromeStyle.systemNavigationBarContrastEnforced); -// } + if (systemChromeStyle.systemNavigationBarContrastEnforced != null && Build.VERSION.SDK_INT >= 29) { + window.setNavigationBarContrastEnforced(systemChromeStyle.systemNavigationBarContrastEnforced); + } view.setSystemUiVisibility(flags); currentTheme = systemChromeStyle; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm index b4d7f4f00319c..16c032fe5e426 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm @@ -74,6 +74,9 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } else if ([method isEqualToString:@"SystemChrome.setEnabledSystemUIOverlays"]) { [self setSystemChromeEnabledSystemUIOverlays:args]; result(nil); + } else if ([method isEqualToString:@"SystemChrome.setEnabledSystemUIMode"]) { + [self setSystemChromeEnabledSystemUIMode:args]; + result(nil); } else if ([method isEqualToString:@"SystemChrome.restoreSystemUIOverlays"]) { [self restoreSystemChromeSystemUIOverlays]; result(nil); @@ -176,6 +179,26 @@ - (void)setSystemChromeEnabledSystemUIOverlays:(NSArray*)overlays { } } +- (void)setSystemChromeEnabledSystemUIMode:(NSObject*)mode enabledOverlays:(NSArray*)overlays { + // Checks if the top status bar should be visible. This platform ignores all + // other overlays and UI modes + + // We opt out of view controller based status bar visibility since we want + // to be able to modify this on the fly. The key used is + // UIViewControllerBasedStatusBarAppearance + [UIApplication sharedApplication].statusBarHidden = + ![overlays containsObject:@"SystemUiOverlay.top"]; + if ([overlays containsObject:@"SystemUiOverlay.bottom"]) { + [[NSNotificationCenter defaultCenter] + postNotificationName:FlutterViewControllerShowHomeIndicator + object:nil]; + } else { + [[NSNotificationCenter defaultCenter] + postNotificationName:FlutterViewControllerHideHomeIndicator + object:nil]; + } +} + - (void)restoreSystemChromeSystemUIOverlays { // Nothing to do on iOS. } diff --git a/shell/platform/fuchsia/flutter/compilation_trace.txt b/shell/platform/fuchsia/flutter/compilation_trace.txt index 95026cf438233..a22804e704964 100644 --- a/shell/platform/fuchsia/flutter/compilation_trace.txt +++ b/shell/platform/fuchsia/flutter/compilation_trace.txt @@ -5267,9 +5267,11 @@ package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,SystemUiOve package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:statusBarBrightness package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:statusBarColor package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:statusBarIconBrightness +package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:systemStatusBarContrastEnforced package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:systemNavigationBarColor package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:systemNavigationBarDividerColor package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:systemNavigationBarIconBrightness +package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:systemNavigationBarContrastEnforced package:flutter/src/widgets/app.dart,WidgetsApp,get:builder package:flutter/src/widgets/app.dart,WidgetsApp,get:localizationsDelegates package:flutter/src/widgets/app.dart,WidgetsApp,get:pageRouteBuilder From 5742cdcc8a27e020f84dc14b23e026f002f29c8b Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Mon, 26 Apr 2021 17:30:52 -0500 Subject: [PATCH 05/28] ++ --- .../systemchannels/PlatformChannel.java | 49 +++++++++++++------ .../plugin/platform/PlatformPlugin.java | 6 +-- .../framework/Source/FlutterPlatformPlugin.mm | 10 ++-- 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index 88222c9c72a6d..6ad6e5d49d14b 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -102,6 +102,18 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result.error("error", exception.getMessage(), null); } break; + case "SystemChrome.setEnabledSystemUIMode": + try { + SystemUiMode mode = decodeSystemUiMode((JSONArray) arguments); + platformMessageHandler.showSystemUiMode(mode); + result.success(null); + } catch (JSONException | NoSuchFieldException exception) { + // JSONException: One or more expected fields were either omitted or referenced an + // invalid type. + // NoSuchFieldException: One or more of the overlay names are invalid. + result.error("error", exception.getMessage(), null); + } + break; case "SystemChrome.restoreSystemUIOverlays": platformMessageHandler.restoreSystemUiOverlays(); result.success(null); @@ -334,8 +346,6 @@ private SystemUiMode decodeSystemUiMode(@NonNull JSONObject encodedSystemUiMode) return SystemUiMode.IMMERSIVE_STICKY; case EDGE_TO_EDGE: return SystemUiMode.EDGE_TO_EDGE; - case MANUAL: - return SystemUiMode.MANUAL; } } @@ -353,9 +363,11 @@ private SystemChromeStyle decodeSystemChromeStyle(@NonNull JSONObject encodedSty Integer systemNavigationBarColor = null; // TODO(mattcarroll): add color annotation Integer systemNavigationBarDividerColor = null; + boolean systemNavigationBarContrastEnforced = null; Brightness statusBarIconBrightness = null; // TODO(mattcarroll): add color annotation Integer statusBarColor = null; + boolean systemStatusBarContrastEnforced = null; if (!encodedStyle.isNull("systemNavigationBarIconBrightness")) { systemNavigationBarIconBrightness = @@ -366,6 +378,14 @@ private SystemChromeStyle decodeSystemChromeStyle(@NonNull JSONObject encodedSty systemNavigationBarColor = encodedStyle.getInt("systemNavigationBarColor"); } + if (!encodedStyle.isNull("systemNavigationBarContrastEnforced")) { + systemNavigationBarContrastEnforced = encodedStyle.getBoolean("systemNavigationBarContrastEnforced"); + } + + if (!encodedStyle.isNull("systemNavigationBarDividerColor")) { + systemNavigationBarDividerColor = encodedStyle.getInt("systemNavigationBarDividerColor"); + } + if (!encodedStyle.isNull("statusBarIconBrightness")) { statusBarIconBrightness = Brightness.fromValue(encodedStyle.getString("statusBarIconBrightness")); @@ -375,16 +395,18 @@ private SystemChromeStyle decodeSystemChromeStyle(@NonNull JSONObject encodedSty statusBarColor = encodedStyle.getInt("statusBarColor"); } - if (!encodedStyle.isNull("systemNavigationBarDividerColor")) { - systemNavigationBarDividerColor = encodedStyle.getInt("systemNavigationBarDividerColor"); + if (!encodedStyle.isNull("systemStatusBarContrastEnforced")) { + systemStatusBarContrastEnforced = encodedStyle.getBoolean("systemStatusBarContrastEnforced"); } return new SystemChromeStyle( statusBarColor, statusBarIconBrightness, + systemStatusBarContrastEnforced, systemNavigationBarColor, systemNavigationBarIconBrightness, - systemNavigationBarDividerColor); + systemNavigationBarDividerColor, + systemNavigationBarContrastEnforced); } /** @@ -442,15 +464,9 @@ public interface PlatformMessageHandler { *

{@link SystemUiMode#EDGE_TO_EDGE} refers to a layout configuration that will consume the full viewport. This * full screen experience does not hide status bars. These status bars can be set to transparent, making the buttons * and icons hover over the fullscreen application. - * - *

{@link SystemUiMode#MANUAL} allows for manual configuration of system status bars. These can be set with the - * given {@code overlays}. {@link SystemUiOverlay#TOP_OVERLAYS} refers to system overlays such as the status bar, - * while {@link SystemUiOverlay#BOTTOM_OVERLAYS} refers to system overlays such as the - * back/home/recents navigation on the bottom of the screen. An empty list of {@code overlays} should hide all - * system overlays. */ // TODO(Piinks): add callback for system Ui change - void showSystemUiMode(@NonNull SystemUiMode mode, @Nullable List overlays); + void showSystemUiMode(@NonNull SystemUiMode mode); /** * The Flutter application would like to restore the visibility of system overlays to the last @@ -603,7 +619,6 @@ public enum SystemUiMode { IMMERSIVE("SystemUiMode.immersive"), IMMERSIVE_STICKY("SystemUiMode.immersive_sticky"), EDGE_TO_EDGE("SystemUiMode.edge_to_edge"), - MANUAL("SystemUiMode.manual"); @NonNull static SystemUiMode fromValue(@NonNull String encodedName) throws NoSuchFieldException { @@ -642,23 +657,29 @@ public static class SystemChromeStyle { // TODO(mattcarroll): add color annotation @Nullable public final Integer statusBarColor; @Nullable public final Brightness statusBarIconBrightness; + @Nullable public final boolean systemStatusBarContrastEnforced; // TODO(mattcarroll): add color annotation @Nullable public final Integer systemNavigationBarColor; @Nullable public final Brightness systemNavigationBarIconBrightness; // TODO(mattcarroll): add color annotation @Nullable public final Integer systemNavigationBarDividerColor; + @Nullable public final boolean systemNavigationBarContrastEnforced; public SystemChromeStyle( @Nullable Integer statusBarColor, @Nullable Brightness statusBarIconBrightness, + @Nullable boolean systemStatusBarContrastEnforced, @Nullable Integer systemNavigationBarColor, @Nullable Brightness systemNavigationBarIconBrightness, - @Nullable Integer systemNavigationBarDividerColor) { + @Nullable Integer systemNavigationBarDividerColor, + @Nullable boolean systemNavigationBarContrastEnforced) { this.statusBarColor = statusBarColor; this.statusBarIconBrightness = statusBarIconBrightness; + this.systemStatusBarContrastEnforced = systemStatusBarContrastEnforced; this.systemNavigationBarColor = systemNavigationBarColor; this.systemNavigationBarIconBrightness = systemNavigationBarIconBrightness; this.systemNavigationBarDividerColor = systemNavigationBarDividerColor; + this.systemNavigationBarContrastEnforced = systemNavigationBarContrastEnforced; } } diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 7c6709de91d4d..11eaefe15a5c5 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -86,8 +86,8 @@ public void showSystemOverlays(@NonNull List ov } @Override - public void showSystemUiMode(@NonNull SystemUiMode mode, @Nullable List overlays) { - setSystemChromeEnabledSystemUIMode(mode, overlays); + public void showSystemUiMode(@NonNull SystemUiMode mode) { + setSystemChromeEnabledSystemUIMode(mode); } @Override @@ -317,8 +317,6 @@ public void onSystemUiVisibilityChange(int visibility) { updateSystemUiOverlays(); } - // This method is deprecated, use setSystemChromeEnabledSystemUIMode instead. - @Deprecated private void setSystemChromeEnabledSystemUIOverlays( List overlaysToShow) { // Start by assuming we want to hide all system overlays (like an immersive diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm index 16c032fe5e426..638427674e0ad 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm @@ -179,16 +179,16 @@ - (void)setSystemChromeEnabledSystemUIOverlays:(NSArray*)overlays { } } -- (void)setSystemChromeEnabledSystemUIMode:(NSObject*)mode enabledOverlays:(NSArray*)overlays { - // Checks if the top status bar should be visible. This platform ignores all - // other overlays and UI modes +- (void)setSystemChromeEnabledSystemUIOverlays:(NSString*)mode { + // Checks if the top status bar should be visible, reflected by edge to edge setting. This platform ignores all + // other system ui modes. // We opt out of view controller based status bar visibility since we want // to be able to modify this on the fly. The key used is // UIViewControllerBasedStatusBarAppearance [UIApplication sharedApplication].statusBarHidden = - ![overlays containsObject:@"SystemUiOverlay.top"]; - if ([overlays containsObject:@"SystemUiOverlay.bottom"]) { + ![mode isEqualToString:@"SystemUiMode.edge_to_edge"]; + if ([mode isEqualToString:@"SystemUiMode.edge_to_edge"]) { [[NSNotificationCenter defaultCenter] postNotificationName:FlutterViewControllerShowHomeIndicator object:nil]; From f5e0e40993bc40502f64246535f74150467f09f9 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Mon, 26 Apr 2021 18:05:30 -0500 Subject: [PATCH 06/28] ++ --- .../systemchannels/PlatformChannel.java | 16 ++++--- .../plugin/platform/PlatformPlugin.java | 44 +++++-------------- 2 files changed, 20 insertions(+), 40 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index 6ad6e5d49d14b..dd29c6abbe7ce 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -104,7 +104,7 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result break; case "SystemChrome.setEnabledSystemUIMode": try { - SystemUiMode mode = decodeSystemUiMode((JSONArray) arguments); + SystemUiMode mode = decodeSystemUiMode((String) arguments); platformMessageHandler.showSystemUiMode(mode); result.success(null); } catch (JSONException | NoSuchFieldException exception) { @@ -333,10 +333,9 @@ private List decodeSystemUiOverlays(@NonNull JSONArray encodedS * @throws NoSuchFieldException if any of the given encoded mode name is invalid. */ @NonNull - private SystemUiMode decodeSystemUiMode(@NonNull JSONObject encodedSystemUiMode) + private SystemUiMode decodeSystemUiMode(@NonNull String encodedSystemUiMode) throws JSONException, NoSuchFieldException { - String encodedMode = encodedSystemUiMode.getString(i); - SystemUiMode mode = SystemUiMode.fromValue(encodedMode); + SystemUiMode mode = SystemUiMode.fromValue(encodedSystemUiMode); switch (mode) { case LEAN_BACK: return SystemUiMode.LEAN_BACK; @@ -347,6 +346,9 @@ private SystemUiMode decodeSystemUiMode(@NonNull JSONObject encodedSystemUiMode) case EDGE_TO_EDGE: return SystemUiMode.EDGE_TO_EDGE; } + + // Execution should never ever get this far, but if it does, we default to edge to edge. + return SystemUiMode.EDGE_TO_EDGE; } /** @@ -363,11 +365,11 @@ private SystemChromeStyle decodeSystemChromeStyle(@NonNull JSONObject encodedSty Integer systemNavigationBarColor = null; // TODO(mattcarroll): add color annotation Integer systemNavigationBarDividerColor = null; - boolean systemNavigationBarContrastEnforced = null; + boolean systemNavigationBarContrastEnforced = true; Brightness statusBarIconBrightness = null; // TODO(mattcarroll): add color annotation Integer statusBarColor = null; - boolean systemStatusBarContrastEnforced = null; + boolean systemStatusBarContrastEnforced = true; if (!encodedStyle.isNull("systemNavigationBarIconBrightness")) { systemNavigationBarIconBrightness = @@ -618,7 +620,7 @@ public enum SystemUiMode { LEAN_BACK("SystemUiMode.lean_back"), IMMERSIVE("SystemUiMode.immersive"), IMMERSIVE_STICKY("SystemUiMode.immersive_sticky"), - EDGE_TO_EDGE("SystemUiMode.edge_to_edge"), + EDGE_TO_EDGE("SystemUiMode.edge_to_edge"); @NonNull static SystemUiMode fromValue(@NonNull String encodedName) throws NoSuchFieldException { diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 11eaefe15a5c5..109967edfa101 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -86,7 +86,7 @@ public void showSystemOverlays(@NonNull List ov } @Override - public void showSystemUiMode(@NonNull SystemUiMode mode) { + public void showSystemUiMode(@NonNull PlatformChannel.SystemUiMode mode) { setSystemChromeEnabledSystemUIMode(mode); } @@ -209,14 +209,14 @@ private void setSystemChromeApplicationSwitcherDescription( } } - private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode systemUiMode, @Nullable List manualOverlaysToShow) { + private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode systemUiMode) { int enabledOverlays = DEFAULT_SYSTEM_UI | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - if (systemUiMode == LEAN_BACK && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + if (systemUiMode == PlatformChannel.SystemUiMode.LEAN_BACK && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { // LEAN BACK // Available starting at SDK 16 // Should not show overlays, tap to reveal overlays, needs onChange callback @@ -229,7 +229,7 @@ private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode sys | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN; - } else if (systemUiMode == IMMERSIVE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + } else if (systemUiMode == PlatformChannel.SystemUiMode.IMMERSIVE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // IMMERSIVE // Available starting at 19 // Should not show overlays, swipe from edges to revela overlays, needs onChange callback @@ -243,7 +243,7 @@ private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode sys | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN; - } else if (systemUiMode == IMMERSIVE_STICKY && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + } else if (systemUiMode == PlatformChannel.SystemUiMode.IMMERSIVE_STICKY && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // STICKY IMMERSIVE // Available starting at 19 // Should not show overlays, swipe from edges to reveal overlays. The app will also receive the swipe gesture. @@ -256,7 +256,7 @@ private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode sys | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN; - } else if (systemUiMode == EDGE_TO_EDGE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + } else if (systemUiMode == PlatformChannel.SystemUiMode.EDGE_TO_EDGE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { // EDGE TO EDGE // Available starting at 16 // SDK 29 and up will apply a translucent body scrim behind 2/3 button navigation bars to ensure contrast with @@ -266,28 +266,6 @@ private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode sys enabledOverlays = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; - } else if (systemUiMode == MANUAL) { - // MANUAL - // Use original implementation of setSystemChromeEnabledSystemUIOverlays for backwards compatibility - - // The SYSTEM_UI_FLAG_IMMERSIVE_STICKY flag was introduced in API 19, so we apply it if desired, and if the - // current Android version is 19 or greater. - if (overlaysToShow.size() == 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - enabledOverlays |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; - } - // Apply any specified overlays - for (int i = 0; i < overlaysToShow.size(); ++i) { - PlatformChannel.SystemUiOverlay overlayToShow = overlaysToShow.get(i); - switch (overlayToShow) { - case TOP_OVERLAYS: - enabledOverlays &= ~View.SYSTEM_UI_FLAG_FULLSCREEN; - break; - case BOTTOM_OVERLAYS: - enabledOverlays &= ~View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; // <- This flag blocks edge to edge - enabledOverlays &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - break; - } - } } // Set up a listener to notify the framework when the system ui has changed. @@ -384,7 +362,7 @@ private void setSystemChromeSystemUIOverlayStyle( window.setStatusBarColor(systemChromeStyle.statusBarColor); } // You can't change the color of the status icons until SDK 23. - if (systemChromeStyle.statusBarIconBrightness != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.MARSHMALLOW) { + if (systemChromeStyle.statusBarIconBrightness != null && Build.VERSION.SDK_INT >= 23) { switch (systemChromeStyle.statusBarIconBrightness) { case DARK: // View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR @@ -398,7 +376,7 @@ private void setSystemChromeSystemUIOverlayStyle( // You can't override the enforced contrast for a transparent status bar until SDK 29. // This overrides the translucent scrim that may be placed behind the bar on SDK 29+ to ensure // contrast is appropriate when using full screen layout modes like Edge to Edge. - if (systemChromeStyle.systemStatusBarContrastEnforced != null && Build.VERSION.SDK_INT >= 29) { + if (!systemChromeStyle.systemStatusBarContrastEnforced && Build.VERSION.SDK_INT >= 29) { window.setStatusBarContrastEnforced(systemChromeStyle.systemStatusBarContrastEnforced); } @@ -410,7 +388,7 @@ private void setSystemChromeSystemUIOverlayStyle( window.setNavigationBarColor(systemChromeStyle.systemNavigationBarColor); } // You can't change the color of the navigation buttons until SDK 26. - if (systemChromeStyle.systemNavigationBarIconBrightness != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.OREO) { + if (systemChromeStyle.systemNavigationBarIconBrightness != null && Build.VERSION.SDK_INT >= 26) { switch (systemChromeStyle.systemNavigationBarIconBrightness) { case DARK: // View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR @@ -422,7 +400,7 @@ private void setSystemChromeSystemUIOverlayStyle( } } // You can't change the color of the navigation bar divider color until SDK 28. - if (systemChromeStyle.systemNavigationBarDividerColor != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.PIE) { + if (systemChromeStyle.systemNavigationBarDividerColor != null && Build.VERSION.SDK_INT >= 28) { window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); window.setNavigationBarDividerColor(systemChromeStyle.systemNavigationBarDividerColor); @@ -431,7 +409,7 @@ private void setSystemChromeSystemUIOverlayStyle( // You can't override the enforced contrast for a transparent navigation bar until SDK 29. // This overrides the translucent scrim that may be placed behind 2/3 button navigation bars on SDK 29+ to ensure // contrast is appropriate when using full screen layout modes like Edge to Edge. - if (systemChromeStyle.systemNavigationBarContrastEnforced != null && Build.VERSION.SDK_INT >= 29) { + if (!systemChromeStyle.systemNavigationBarContrastEnforced && Build.VERSION.SDK_INT >= 29) { window.setNavigationBarContrastEnforced(systemChromeStyle.systemNavigationBarContrastEnforced); } From ec0068f3d5c9b9d59fea2902080d9aa6b4135f26 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Tue, 27 Apr 2021 10:51:27 -0500 Subject: [PATCH 07/28] ++ --- .../systemchannels/PlatformChannel.java | 42 +++++++++---------- .../fuchsia/flutter/compilation_trace.txt | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index dd29c6abbe7ce..d9f807c590088 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -360,45 +360,45 @@ private SystemUiMode decodeSystemUiMode(@NonNull String encodedSystemUiMode) @NonNull private SystemChromeStyle decodeSystemChromeStyle(@NonNull JSONObject encodedStyle) throws JSONException, NoSuchFieldException { - Brightness systemNavigationBarIconBrightness = null; + // TODO(mattcarroll): add color annotation + Integer statusBarColor = null; + Brightness statusBarIconBrightness = null; + boolean systemStatusBarContrastEnforced = true; // TODO(mattcarroll): add color annotation Integer systemNavigationBarColor = null; + Brightness systemNavigationBarIconBrightness = null; // TODO(mattcarroll): add color annotation Integer systemNavigationBarDividerColor = null; boolean systemNavigationBarContrastEnforced = true; - Brightness statusBarIconBrightness = null; - // TODO(mattcarroll): add color annotation - Integer statusBarColor = null; - boolean systemStatusBarContrastEnforced = true; - if (!encodedStyle.isNull("systemNavigationBarIconBrightness")) { - systemNavigationBarIconBrightness = - Brightness.fromValue(encodedStyle.getString("systemNavigationBarIconBrightness")); + if (!encodedStyle.isNull("statusBarColor")) { + statusBarColor = encodedStyle.getInt("statusBarColor"); } - if (!encodedStyle.isNull("systemNavigationBarColor")) { - systemNavigationBarColor = encodedStyle.getInt("systemNavigationBarColor"); + if (!encodedStyle.isNull("statusBarIconBrightness")) { + statusBarIconBrightness = + Brightness.fromValue(encodedStyle.getString("statusBarIconBrightness")); } - if (!encodedStyle.isNull("systemNavigationBarContrastEnforced")) { - systemNavigationBarContrastEnforced = encodedStyle.getBoolean("systemNavigationBarContrastEnforced"); + if (!encodedStyle.isNull("systemStatusBarContrastEnforced")) { + systemStatusBarContrastEnforced = encodedStyle.getBoolean("systemStatusBarContrastEnforced"); } - if (!encodedStyle.isNull("systemNavigationBarDividerColor")) { - systemNavigationBarDividerColor = encodedStyle.getInt("systemNavigationBarDividerColor"); + if (!encodedStyle.isNull("systemNavigationBarColor")) { + systemNavigationBarColor = encodedStyle.getInt("systemNavigationBarColor"); } - if (!encodedStyle.isNull("statusBarIconBrightness")) { - statusBarIconBrightness = - Brightness.fromValue(encodedStyle.getString("statusBarIconBrightness")); + if (!encodedStyle.isNull("systemNavigationBarIconBrightness")) { + systemNavigationBarIconBrightness = + Brightness.fromValue(encodedStyle.getString("systemNavigationBarIconBrightness")); } - if (!encodedStyle.isNull("statusBarColor")) { - statusBarColor = encodedStyle.getInt("statusBarColor"); + if (!encodedStyle.isNull("systemNavigationBarDividerColor")) { + systemNavigationBarDividerColor = encodedStyle.getInt("systemNavigationBarDividerColor"); } - if (!encodedStyle.isNull("systemStatusBarContrastEnforced")) { - systemStatusBarContrastEnforced = encodedStyle.getBoolean("systemStatusBarContrastEnforced"); + if (!encodedStyle.isNull("systemNavigationBarContrastEnforced")) { + systemNavigationBarContrastEnforced = encodedStyle.getBoolean("systemNavigationBarContrastEnforced"); } return new SystemChromeStyle( diff --git a/shell/platform/fuchsia/flutter/compilation_trace.txt b/shell/platform/fuchsia/flutter/compilation_trace.txt index a22804e704964..32a65f153ca69 100644 --- a/shell/platform/fuchsia/flutter/compilation_trace.txt +++ b/shell/platform/fuchsia/flutter/compilation_trace.txt @@ -5269,8 +5269,8 @@ package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:statusB package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:statusBarIconBrightness package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:systemStatusBarContrastEnforced package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:systemNavigationBarColor -package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:systemNavigationBarDividerColor package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:systemNavigationBarIconBrightness +package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:systemNavigationBarDividerColor package:flutter/src/services/system_chrome.dart,SystemUiOverlayStyle,get:systemNavigationBarContrastEnforced package:flutter/src/widgets/app.dart,WidgetsApp,get:builder package:flutter/src/widgets/app.dart,WidgetsApp,get:localizationsDelegates From 588d26a05e519c6a5e42a0a63c5b1513d6a1ab4f Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Thu, 3 Jun 2021 17:34:45 -0500 Subject: [PATCH 08/28] ++ --- .../engine/systemchannels/PlatformChannel.java | 6 +++--- .../flutter/plugin/platform/PlatformPlugin.java | 16 ++++++++-------- .../framework/Source/FlutterPlatformPlugin.mm | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index d9f807c590088..049f686973e20 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -617,10 +617,10 @@ static SystemUiOverlay fromValue(@NonNull String encodedName) throws NoSuchField * The set of Android system fullscreen modes as perceived by the Flutter application. */ public enum SystemUiMode { - LEAN_BACK("SystemUiMode.lean_back"), + LEAN_BACK("SystemUiMode.leanBack"), IMMERSIVE("SystemUiMode.immersive"), - IMMERSIVE_STICKY("SystemUiMode.immersive_sticky"), - EDGE_TO_EDGE("SystemUiMode.edge_to_edge"); + IMMERSIVE_STICKY("SystemUiMode.immersiveSticky"), + EDGE_TO_EDGE("SystemUiMode.edgeToEdge"); @NonNull static SystemUiMode fromValue(@NonNull String encodedName) throws NoSuchFieldException { diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 109967edfa101..079f42c2f04a2 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -211,10 +211,10 @@ private void setSystemChromeApplicationSwitcherDescription( private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode systemUiMode) { int enabledOverlays = - DEFAULT_SYSTEM_UI - | View.SYSTEM_UI_FLAG_FULLSCREEN - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + DEFAULT_SYSTEM_UI + | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; if (systemUiMode == PlatformChannel.SystemUiMode.LEAN_BACK && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { // LEAN BACK @@ -300,10 +300,10 @@ private void setSystemChromeEnabledSystemUIOverlays( // Start by assuming we want to hide all system overlays (like an immersive // game). int enabledOverlays = - DEFAULT_SYSTEM_UI - | View.SYSTEM_UI_FLAG_FULLSCREEN - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + DEFAULT_SYSTEM_UI + | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; // The SYSTEM_UI_FLAG_IMMERSIVE_STICKY flag was introduced in API 19, so we // apply it diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm index 638427674e0ad..87132c878d3d0 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm @@ -187,8 +187,8 @@ - (void)setSystemChromeEnabledSystemUIOverlays:(NSString*)mode { // to be able to modify this on the fly. The key used is // UIViewControllerBasedStatusBarAppearance [UIApplication sharedApplication].statusBarHidden = - ![mode isEqualToString:@"SystemUiMode.edge_to_edge"]; - if ([mode isEqualToString:@"SystemUiMode.edge_to_edge"]) { + ![mode isEqualToString:@"SystemUiMode.edgeToEdge"]; + if ([mode isEqualToString:@"SystemUiMode.edgeToEdge"]) { [[NSNotificationCenter defaultCenter] postNotificationName:FlutterViewControllerShowHomeIndicator object:nil]; From f5533c5822ac85d73fd63fbd8580d1fb50580b64 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Fri, 4 Jun 2021 14:47:55 -0500 Subject: [PATCH 09/28] Formatting updates --- .../plugin/platform/PlatformPlugin.java | 100 ++++++++++-------- .../plugin/platform/PlatformPluginTest.java | 3 +- .../framework/Source/FlutterPlatformPlugin.mm | 6 +- 3 files changed, 62 insertions(+), 47 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 079f42c2f04a2..0f50c721c0af4 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -216,39 +216,44 @@ private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode sys | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - if (systemUiMode == PlatformChannel.SystemUiMode.LEAN_BACK && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + if (systemUiMode == PlatformChannel.SystemUiMode.LEAN_BACK + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { // LEAN BACK // Available starting at SDK 16 // Should not show overlays, tap to reveal overlays, needs onChange callback - // When the overlays come in on tap, the app does not recieve the gesture and does not know the system overlay - // has changed. The overlays cannot be dismissed, so adding the callback support will allow users to restore - // the system ui and dismiss the overlays. + // When the overlays come in on tap, the app does not recieve the gesture and does not know + // the system overlay has changed. The overlays cannot be dismissed, so adding the callback + // support will allow users to restore the system ui and dismiss the overlays. // Not compatible with top/bottom overlays enabled. - enabledOverlays = View.SYSTEM_UI_FLAG_LAYOUT_STABLE + enabledOverlays = + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN; - } else if (systemUiMode == PlatformChannel.SystemUiMode.IMMERSIVE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + } else if (systemUiMode == PlatformChannel.SystemUiMode.IMMERSIVE + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // IMMERSIVE // Available starting at 19 // Should not show overlays, swipe from edges to revela overlays, needs onChange callback - // When the overlays come in on swipe, the app does not receive the gesture and does not know the system overlay - // has changed. The overlays cannot be dismissed, so adding callback support will allow users to restore the - // system ui and dismiss the overlays. + // When the overlays come in on swipe, the app does not receive the gesture and does not know + // the system overlay has changed. The overlays cannot be dismissed, so adding callback + // support will allow users to restore the system ui and dismiss the overlays. // Not compatible with top/bottom overlays enabled. - enabledOverlays = View.SYSTEM_UI_FLAG_IMMERSIVE + enabledOverlays = + View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN; - } else if (systemUiMode == PlatformChannel.SystemUiMode.IMMERSIVE_STICKY && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + } else if (systemUiMode == PlatformChannel.SystemUiMode.IMMERSIVE_STICKY + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // STICKY IMMERSIVE // Available starting at 19 - // Should not show overlays, swipe from edges to reveal overlays. The app will also receive the swipe gesture. - // The overlays cannot be dismissed, so adding callback support will allow users to restore the - // system ui and dismiss the overlays. + // Should not show overlays, swipe from edges to reveal overlays. The app will also receive + // the swipe gesture. The overlays cannot be dismissed, so adding callback support will + // allow users to restore the system ui and dismiss the overlays. // Not compatible with top/bottom overlays enabled. enabledOverlays = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_LAYOUT_STABLE @@ -256,11 +261,12 @@ private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode sys | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN; - } else if (systemUiMode == PlatformChannel.SystemUiMode.EDGE_TO_EDGE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + } else if (systemUiMode == PlatformChannel.SystemUiMode.EDGE_TO_EDGE + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { // EDGE TO EDGE // Available starting at 16 - // SDK 29 and up will apply a translucent body scrim behind 2/3 button navigation bars to ensure contrast with - // buttons on the nav bar. + // SDK 29 and up will apply a translucent body scrim behind 2/3 button navigation bars + // to ensure contrast with buttons on the nav bar. // SDK 28 and lower will support a transparent 2/3 button navigation bar. // Overlays should be included and not removed. enabledOverlays = View.SYSTEM_UI_FLAG_LAYOUT_STABLE @@ -269,27 +275,30 @@ private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode sys } // Set up a listener to notify the framework when the system ui has changed. - // TODO(Piinks): Document this heavily. E2E would not be a relevant use case for this callback functionality. + // TODO(Piinks): Document this heavily. E2E would not be a relevant use case for this + // callback functionality. View decorView = activity.getWindow().getDecorView(); - decorView.setOnSystemUiVisibilityChangeListener - (new View.OnSystemUiVisibilityChangeListener() { - @Override - public void onSystemUiVisibilityChange(int visibility) { - if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { - // The system bars are visible. Make any desired adjustments to your UI, such as - // showing the action bar or other navigational controls. - // Another common action is to set a timer to dismiss the system bars and restore - // the fullscreen mode that was perviously enabled. - // TODO(Piinks): Wire up callback to the framework - System.out.println("No longer in fullscreen"); - } else { - // The system bars are NOT visible. Make any desired adjustments to your UI, such - // as hiding the action bar or other navigational controls. - // TODO(Piinks): Wire up callback to the framework - System.out.println("Fullscreen"); - } - } - }); + decorView.setOnSystemUiVisibilityChangeListener( + new View.OnSystemUiVisibilityChangeListener() { + @Override + public void onSystemUiVisibilityChange(int visibility) { + if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { + // The system bars are visible. Make any desired adjustments to + // your UI, such as showing the action bar or other navigational + // controls. Another common action is to set a timer to dismiss + // the system bars and restore the fullscreen mode that was + // previously enabled. + // TODO(Piinks): Wire up callback to the framework + System.out.println("Engine says: No longer in fullscreen"); + } else { + // The system bars are NOT visible. Make any desired adjustments + // to your UI, such as hiding the action bar or other + // navigational controls. + // TODO(Piinks): Wire up callback to the framework + System.out.println("Engine says: Fullscreen"); + } + } + }); mEnabledOverlays = enabledOverlays; updateSystemUiOverlays(); @@ -357,8 +366,10 @@ private void setSystemChromeSystemUIOverlayStyle( // SYSTEM STATUS BAR ------------------------------------------------------------------- // You can't change the color of the system status bar until SDK 21. // If transparent, SDK 29 and higher may apply a translucent scrim behind the bar to ensure - // proper contrast. This can be overridden with SystemChromeStyle.systemStatusBarContrastEnforced. - if (systemChromeStyle.statusBarColor != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + // proper contrast. This can be overridden with + // SystemChromeStyle.systemStatusBarContrastEnforced. + if (systemChromeStyle.statusBarColor != null + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { window.setStatusBarColor(systemChromeStyle.statusBarColor); } // You can't change the color of the status icons until SDK 23. @@ -382,13 +393,16 @@ private void setSystemChromeSystemUIOverlayStyle( // SYSTEM NAVIGATION BAR -------------------------------------------------------------- // You can't change the color of the system navigation bar until SDK 21. - // If transparent, SDK 29 and higher may apply a translucent scrim behind 2/3 button navigation bars to ensure - // proper contrast. This can be overridden with SystemChromeStyle.systemNavigationBarContrastEnforced. - if (systemChromeStyle.systemNavigationBarColor != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + // If transparent, SDK 29 and higher may apply a translucent scrim behind 2/3 button navigation + // bars to ensure proper contrast. This can be overridden with + // SystemChromeStyle.systemNavigationBarContrastEnforced. + if (systemChromeStyle.systemNavigationBarColor != null + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { window.setNavigationBarColor(systemChromeStyle.systemNavigationBarColor); } // You can't change the color of the navigation buttons until SDK 26. - if (systemChromeStyle.systemNavigationBarIconBrightness != null && Build.VERSION.SDK_INT >= 26) { + if (systemChromeStyle.systemNavigationBarIconBrightness != null + && Build.VERSION.SDK_INT >= 26) { switch (systemChromeStyle.systemNavigationBarIconBrightness) { case DARK: // View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR diff --git a/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java b/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java index b57d12bac6f81..e878f7a245493 100644 --- a/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java +++ b/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java @@ -129,7 +129,8 @@ public void setNavigationBarDividerColor() { when(fakeActivity.getWindow()).thenReturn(fakeWindow); PlatformChannel fakePlatformChannel = mock(PlatformChannel.class); PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel); - SystemChromeStyle style = new SystemChromeStyle(0XFF000000, null, 0XFFC70039, null, 0XFF006DB3); + SystemChromeStyle style = + new SystemChromeStyle(0XFF000000, null, true, 0XFFC70039, null, 0XFF006DB3, true); if (Build.VERSION.SDK_INT >= 28) { platformPlugin.mPlatformMessageHandler.setSystemUiOverlayStyle(style); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm index 87132c878d3d0..999f81d5bc618 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm @@ -179,9 +179,9 @@ - (void)setSystemChromeEnabledSystemUIOverlays:(NSArray*)overlays { } } -- (void)setSystemChromeEnabledSystemUIOverlays:(NSString*)mode { - // Checks if the top status bar should be visible, reflected by edge to edge setting. This platform ignores all - // other system ui modes. +- (void)setSystemChromeEnabledSystemUIMode:(NSString*)mode { + // Checks if the top status bar should be visible, reflected by edge to edge setting. This + // platform ignores all other system ui modes. // We opt out of view controller based status bar visibility since we want // to be able to modify this on the fly. The key used is From 4a74208beb488d394d36ed8d75a2d5f6a60d7da5 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Fri, 4 Jun 2021 14:50:17 -0500 Subject: [PATCH 10/28] ++ --- .../systemchannels/PlatformChannel.java | 48 ++++++++++--------- .../plugin/platform/PlatformPlugin.java | 14 ++++-- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index 049f686973e20..7c9807f1f3f68 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -328,13 +328,13 @@ private List decodeSystemUiOverlays(@NonNull JSONArray encodedS /** * Decodes an object of JSON-encoded mode to a {@link SystemUiMode}. * - * @throws JSONException if {@code encodedSystemUiMode} does not contain expected keys and - * value types. + * @throws JSONException if {@code encodedSystemUiMode} does not contain expected keys and value + * types. * @throws NoSuchFieldException if any of the given encoded mode name is invalid. */ @NonNull private SystemUiMode decodeSystemUiMode(@NonNull String encodedSystemUiMode) - throws JSONException, NoSuchFieldException { + throws JSONException, NoSuchFieldException { SystemUiMode mode = SystemUiMode.fromValue(encodedSystemUiMode); switch (mode) { case LEAN_BACK: @@ -377,7 +377,7 @@ private SystemChromeStyle decodeSystemChromeStyle(@NonNull JSONObject encodedSty if (!encodedStyle.isNull("statusBarIconBrightness")) { statusBarIconBrightness = - Brightness.fromValue(encodedStyle.getString("statusBarIconBrightness")); + Brightness.fromValue(encodedStyle.getString("statusBarIconBrightness")); } if (!encodedStyle.isNull("systemStatusBarContrastEnforced")) { @@ -398,7 +398,8 @@ private SystemChromeStyle decodeSystemChromeStyle(@NonNull JSONObject encodedSty } if (!encodedStyle.isNull("systemNavigationBarContrastEnforced")) { - systemNavigationBarContrastEnforced = encodedStyle.getBoolean("systemNavigationBarContrastEnforced"); + systemNavigationBarContrastEnforced = + encodedStyle.getBoolean("systemNavigationBarContrastEnforced"); } return new SystemChromeStyle( @@ -450,32 +451,35 @@ public interface PlatformMessageHandler { void showSystemOverlays(@NonNull List overlays); /** - * The Flutter application would like the Android system to display the given {@code mode}, or manually configured - * {@code overlays}. + * The Flutter application would like the Android system to display the given {@code mode}, or + * manually configured {@code overlays}. * - *

{@link SystemUiMode#LEAN_BACK} refers to a fullscreen experience that restores system bars upon tapping - * anywhere in the application. This tap gesture is not received by the application. + *

{@link SystemUiMode#LEAN_BACK} refers to a fullscreen experience that restores system bars + * upon tapping anywhere in the application. This tap gesture is not received by the + * application. * - *

{@link SystemUiMode#IMMERSIVE} refers to a fullscreen experience that restores system bars upon swiping from - * the edge of the viewport. This swipe gesture is not recived by the application. + *

{@link SystemUiMode#IMMERSIVE} refers to a fullscreen experience that restores system bars + * upon swiping from the edge of the viewport. This swipe gesture is not recived by the + * application. * - *

{@link SystemUiMode#IMMERSIVE_STICKY} refers to a fullscreen experience that restores system bars upon swiping - * from the edge of the viewport. This swipe gesture is received by the application, in contrast to - * {@link SystemUiMode#IMMERSIVE}. + *

{@link SystemUiMode#IMMERSIVE_STICKY} refers to a fullscreen experience that restores + * system bars upon swiping from the edge of the viewport. This swipe gesture is received by the + * application, in contrast to {@link SystemUiMode#IMMERSIVE}. * - *

{@link SystemUiMode#EDGE_TO_EDGE} refers to a layout configuration that will consume the full viewport. This - * full screen experience does not hide status bars. These status bars can be set to transparent, making the buttons - * and icons hover over the fullscreen application. + *

{@link SystemUiMode#EDGE_TO_EDGE} refers to a layout configuration that will consume the + * full viewport. This full screen experience does not hide status bars. These status bars can + * be set to transparent, making the buttons and icons hover over the fullscreen application. */ // TODO(Piinks): add callback for system Ui change void showSystemUiMode(@NonNull SystemUiMode mode); /** * The Flutter application would like to restore the visibility of system overlays to the last - * set of overlays sent via {@link #showSystemOverlays(List)} or {@link #showSystemUiMode(SystemUiMode, List)}. + * set of overlays sent via {@link #showSystemOverlays(List)} or {@link + * #showSystemUiMode(SystemUiMode, List)}. * - *

If {@link #showSystemOverlays(List)} or {@link #showSystemUiMode(SystemUiMode, List)} has yet to be called, - * then a default system overlay appearance is desired: + *

If {@link #showSystemOverlays(List)} or {@link #showSystemUiMode(SystemUiMode, List)} has + * yet to be called, then a default system overlay appearance is desired: * *

{@code View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN } */ @@ -613,9 +617,7 @@ static SystemUiOverlay fromValue(@NonNull String encodedName) throws NoSuchField } } - /** - * The set of Android system fullscreen modes as perceived by the Flutter application. - */ + /** The set of Android system fullscreen modes as perceived by the Flutter application. */ public enum SystemUiMode { LEAN_BACK("SystemUiMode.leanBack"), IMMERSIVE("SystemUiMode.immersive"), diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 0f50c721c0af4..078b01db65cdf 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -255,7 +255,8 @@ private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode sys // the swipe gesture. The overlays cannot be dismissed, so adding callback support will // allow users to restore the system ui and dismiss the overlays. // Not compatible with top/bottom overlays enabled. - enabledOverlays = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + enabledOverlays = + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN @@ -269,7 +270,8 @@ private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode sys // to ensure contrast with buttons on the nav bar. // SDK 28 and lower will support a transparent 2/3 button navigation bar. // Overlays should be included and not removed. - enabledOverlays = View.SYSTEM_UI_FLAG_LAYOUT_STABLE + enabledOverlays = + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; } @@ -421,10 +423,12 @@ private void setSystemChromeSystemUIOverlayStyle( } // You can't override the enforced contrast for a transparent navigation bar until SDK 29. - // This overrides the translucent scrim that may be placed behind 2/3 button navigation bars on SDK 29+ to ensure - // contrast is appropriate when using full screen layout modes like Edge to Edge. + // This overrides the translucent scrim that may be placed behind 2/3 button navigation bars on + // SDK 29+ to ensure contrast is appropriate when using full screen layout modes like + // Edge to Edge. if (!systemChromeStyle.systemNavigationBarContrastEnforced && Build.VERSION.SDK_INT >= 29) { - window.setNavigationBarContrastEnforced(systemChromeStyle.systemNavigationBarContrastEnforced); + window.setNavigationBarContrastEnforced( + systemChromeStyle.systemNavigationBarContrastEnforced); } view.setSystemUiVisibility(flags); From 366be11dab8a8dce82b9e15bbef52ee63e909492 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Fri, 4 Jun 2021 18:05:29 -0500 Subject: [PATCH 11/28] Added callback on platform channel --- .../systemchannels/PlatformChannel.java | 15 ++++- .../plugin/platform/PlatformPlugin.java | 57 ++++++++++--------- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index 7c9807f1f3f68..22e1ba767480f 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -14,6 +14,7 @@ import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.json.JSONArray; import org.json.JSONException; @@ -114,6 +115,10 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result.error("error", exception.getMessage(), null); } break; + case "SystemChrome.setSystemUIChangeListener": + platformMessageHandler.setSystemUIChangeListener(); + result.success(null); + break; case "SystemChrome.restoreSystemUIOverlays": platformMessageHandler.restoreSystemUiOverlays(); result.success(null); @@ -206,6 +211,12 @@ public void setPlatformMessageHandler(@Nullable PlatformMessageHandler platformM this.platformMessageHandler = platformMessageHandler; } + /** Informs Flutter of a change in the SystemUI overlays. */ + public void systemChromeChanged(boolean overlaysAreVisible) { + Log.v(TAG, "Sending 'systemUIChange' message."); + channel.invokeMethod("SystemChrome.systemUIChange", Arrays.asList(overlaysAreVisible)); + } + // TODO(mattcarroll): add support for IntDef annotations, then add @ScreenOrientation /** @@ -470,9 +481,11 @@ public interface PlatformMessageHandler { * full viewport. This full screen experience does not hide status bars. These status bars can * be set to transparent, making the buttons and icons hover over the fullscreen application. */ - // TODO(Piinks): add callback for system Ui change void showSystemUiMode(@NonNull SystemUiMode mode); + /** TODO(Piinks): Docs */ + void setSystemUIChangeListener(); + /** * The Flutter application would like to restore the visibility of system overlays to the last * set of overlays sent via {@link #showSystemOverlays(List)} or {@link diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 078b01db65cdf..04fb398e6a068 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -90,6 +90,11 @@ public void showSystemUiMode(@NonNull PlatformChannel.SystemUiMode mode) { setSystemChromeEnabledSystemUIMode(mode); } + @Override + public void setSystemUIChangeListener() { + setSystemChromeChangeListener(); + } + @Override public void restoreSystemUiOverlays() { restoreSystemChromeSystemUIOverlays(); @@ -209,6 +214,32 @@ private void setSystemChromeApplicationSwitcherDescription( } } + private void setSystemChromeChangeListener() { + // Set up a listener to notify the framework when the system ui has changed. + // TODO(Piinks): Document this heavily. E2E would not be a relevant use case for this + // callback functionality. + View decorView = activity.getWindow().getDecorView(); + decorView.setOnSystemUiVisibilityChangeListener( + new View.OnSystemUiVisibilityChangeListener() { + @Override + public void onSystemUiVisibilityChange(int visibility) { + if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { + // The system bars are visible. Make any desired adjustments to + // your UI, such as showing the action bar or other navigational + // controls. Another common action is to set a timer to dismiss + // the system bars and restore the fullscreen mode that was + // previously enabled. + platformChannel.systemChromeChanged(false); + } else { + // The system bars are NOT visible. Make any desired adjustments + // to your UI, such as hiding the action bar or other + // navigational controls. + platformChannel.systemChromeChanged(true); + } + } + }); + } + private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode systemUiMode) { int enabledOverlays = DEFAULT_SYSTEM_UI @@ -276,32 +307,6 @@ private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode sys | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; } - // Set up a listener to notify the framework when the system ui has changed. - // TODO(Piinks): Document this heavily. E2E would not be a relevant use case for this - // callback functionality. - View decorView = activity.getWindow().getDecorView(); - decorView.setOnSystemUiVisibilityChangeListener( - new View.OnSystemUiVisibilityChangeListener() { - @Override - public void onSystemUiVisibilityChange(int visibility) { - if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { - // The system bars are visible. Make any desired adjustments to - // your UI, such as showing the action bar or other navigational - // controls. Another common action is to set a timer to dismiss - // the system bars and restore the fullscreen mode that was - // previously enabled. - // TODO(Piinks): Wire up callback to the framework - System.out.println("Engine says: No longer in fullscreen"); - } else { - // The system bars are NOT visible. Make any desired adjustments - // to your UI, such as hiding the action bar or other - // navigational controls. - // TODO(Piinks): Wire up callback to the framework - System.out.println("Engine says: Fullscreen"); - } - } - }); - mEnabledOverlays = enabledOverlays; updateSystemUiOverlays(); } From 65a42325a8579fb312dd113530a7c02f31e557b3 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Tue, 8 Jun 2021 14:57:13 -0500 Subject: [PATCH 12/28] ++ --- .../engine/systemchannels/PlatformChannel.java | 12 +++++++++--- .../io/flutter/plugin/platform/PlatformPlugin.java | 2 -- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index 22e1ba767480f..c4d003b74f371 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -116,7 +116,7 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result } break; case "SystemChrome.setSystemUIChangeListener": - platformMessageHandler.setSystemUIChangeListener(); + platformMessageHandler.setSystemUiChangeListener(); result.success(null); break; case "SystemChrome.restoreSystemUIOverlays": @@ -483,8 +483,14 @@ public interface PlatformMessageHandler { */ void showSystemUiMode(@NonNull SystemUiMode mode); - /** TODO(Piinks): Docs */ - void setSystemUIChangeListener(); + /** + * The Flutter application would like the Android system to notify the framework when the system + * ui visibility has changed. + * + * This is relevant when using {@link SystemUiMode}s for fullscreen applications, from + * which the system overlays can appear or disappear based on user input. + */ + void setSystemUiChangeListener(); /** * The Flutter application would like to restore the visibility of system overlays to the last diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 04fb398e6a068..3ca668d9606f8 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -216,8 +216,6 @@ private void setSystemChromeApplicationSwitcherDescription( private void setSystemChromeChangeListener() { // Set up a listener to notify the framework when the system ui has changed. - // TODO(Piinks): Document this heavily. E2E would not be a relevant use case for this - // callback functionality. View decorView = activity.getWindow().getDecorView(); decorView.setOnSystemUiVisibilityChangeListener( new View.OnSystemUiVisibilityChangeListener() { From b935754fc0f79855a8a34faea8f4bbbb8b605cc4 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Tue, 8 Jun 2021 16:21:24 -0500 Subject: [PATCH 13/28] Typo --- .../android/io/flutter/plugin/platform/PlatformPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 3ca668d9606f8..30bb57551e016 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -91,7 +91,7 @@ public void showSystemUiMode(@NonNull PlatformChannel.SystemUiMode mode) { } @Override - public void setSystemUIChangeListener() { + public void setSystemUiChangeListener() { setSystemChromeChangeListener(); } From 3ed55852d0ea0b56a9907a3172884e6efc48dc13 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Tue, 8 Jun 2021 16:36:17 -0500 Subject: [PATCH 14/28] Fix formatting --- .../embedding/engine/systemchannels/PlatformChannel.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index c4d003b74f371..7c8e8a7c8027d 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -487,8 +487,8 @@ public interface PlatformMessageHandler { * The Flutter application would like the Android system to notify the framework when the system * ui visibility has changed. * - * This is relevant when using {@link SystemUiMode}s for fullscreen applications, from - * which the system overlays can appear or disappear based on user input. + *

This is relevant when using {@link SystemUiMode}s for fullscreen applications, from which + * the system overlays can appear or disappear based on user input. */ void setSystemUiChangeListener(); From 74d2e9a78d64988d777426bd6ba4e9b30dfdf156 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Mon, 21 Jun 2021 17:40:50 -0500 Subject: [PATCH 15/28] Update shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java Co-authored-by: Shi-Hao Hong --- .../android/io/flutter/plugin/platform/PlatformPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 30bb57551e016..c7170d9cc189d 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -264,7 +264,7 @@ private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode sys && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // IMMERSIVE // Available starting at 19 - // Should not show overlays, swipe from edges to revela overlays, needs onChange callback + // Should not show overlays, swipe from edges to reveal overlays, needs onChange callback // When the overlays come in on swipe, the app does not receive the gesture and does not know // the system overlay has changed. The overlays cannot be dismissed, so adding callback // support will allow users to restore the system ui and dismiss the overlays. From c59f6f84455f5f730b339080aeadbe1fee7c766f Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Wed, 23 Jun 2021 15:57:37 -0500 Subject: [PATCH 16/28] Add more tests --- .../plugin/platform/PlatformPluginTest.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java b/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java index e878f7a245493..5bfe2be576a12 100644 --- a/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java +++ b/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java @@ -141,6 +141,48 @@ public void setNavigationBarDividerColor() { } } + @Config(sdk = 29) + @Test + public void setSystemUiMode() { + View fakeDecorView = mock(View.class); + Window fakeWindow = mock(Window.class); + when(fakeWindow.getDecorView()).thenReturn(fakeDecorView); + Activity fakeActivity = mock(Activity.class); + when(fakeActivity.getWindow()).thenReturn(fakeWindow); + PlatformChannel fakePlatformChannel = mock(PlatformChannel.class); + PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel); + + if (Build.VERSION.SDK_INT >= 28) { + platformPlugin.mPlatformMessageHandler.showSystemUiMode(PlatformChannel.SystemUiMode.LEAN_BACK); + assertEquals(View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN, fakeActivity.getWindow().getSystemUIVisibility()); + + platformPlugin.mPlatformMessageHandler.showSystemUiMode(PlatformChannel.SystemUiMode.IMMERSIVE); + assertEquals(View.SYSTEM_UI_FLAG_IMMERSIVE + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN, fakeActivity.getWindow().getSystemUIVisibility()); + + platformPlugin.mPlatformMessageHandler.showSystemUiMode(PlatformChannel.SystemUiMode.IMMERSIVE_STICKY); + assertEquals(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN, fakeActivity.getWindow().getSystemUIVisibility()); + + platformPlugin.mPlatformMessageHandler.showSystemUiMode(PlatformChannel.SystemUiMode.EDGE_TO_EDGE); + assertEquals(View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, fakeActivity.getWindow().getSystemUIVisibility()); + } + } + @Test public void popSystemNavigatorFlutterActivity() { Activity mockActivity = mock(Activity.class); From 03b22df84c0f88a52b4059a07bfc8ebe55a344d2 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Wed, 23 Jun 2021 15:58:36 -0500 Subject: [PATCH 17/28] Formatting --- .../plugin/platform/PlatformPluginTest.java | 66 +++++++++++-------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java b/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java index 5bfe2be576a12..15ab5e61d341b 100644 --- a/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java +++ b/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java @@ -153,33 +153,45 @@ public void setSystemUiMode() { PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel); if (Build.VERSION.SDK_INT >= 28) { - platformPlugin.mPlatformMessageHandler.showSystemUiMode(PlatformChannel.SystemUiMode.LEAN_BACK); - assertEquals(View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_FULLSCREEN, fakeActivity.getWindow().getSystemUIVisibility()); - - platformPlugin.mPlatformMessageHandler.showSystemUiMode(PlatformChannel.SystemUiMode.IMMERSIVE); - assertEquals(View.SYSTEM_UI_FLAG_IMMERSIVE - | View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_FULLSCREEN, fakeActivity.getWindow().getSystemUIVisibility()); - - platformPlugin.mPlatformMessageHandler.showSystemUiMode(PlatformChannel.SystemUiMode.IMMERSIVE_STICKY); - assertEquals(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - | View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_FULLSCREEN, fakeActivity.getWindow().getSystemUIVisibility()); - - platformPlugin.mPlatformMessageHandler.showSystemUiMode(PlatformChannel.SystemUiMode.EDGE_TO_EDGE); - assertEquals(View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, fakeActivity.getWindow().getSystemUIVisibility()); + platformPlugin.mPlatformMessageHandler.showSystemUiMode( + PlatformChannel.SystemUiMode.LEAN_BACK); + assertEquals( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN, + fakeActivity.getWindow().getSystemUIVisibility()); + + platformPlugin.mPlatformMessageHandler.showSystemUiMode( + PlatformChannel.SystemUiMode.IMMERSIVE); + assertEquals( + View.SYSTEM_UI_FLAG_IMMERSIVE + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN, + fakeActivity.getWindow().getSystemUIVisibility()); + + platformPlugin.mPlatformMessageHandler.showSystemUiMode( + PlatformChannel.SystemUiMode.IMMERSIVE_STICKY); + assertEquals( + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN, + fakeActivity.getWindow().getSystemUIVisibility()); + + platformPlugin.mPlatformMessageHandler.showSystemUiMode( + PlatformChannel.SystemUiMode.EDGE_TO_EDGE); + assertEquals( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, + fakeActivity.getWindow().getSystemUIVisibility()); } } From 555677c23fbbf2780266b8ada277dd929fe2cb7a Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Wed, 23 Jun 2021 16:15:46 -0500 Subject: [PATCH 18/28] Fix docs and tests --- .../embedding/engine/systemchannels/PlatformChannel.java | 4 ++-- .../io/flutter/plugin/platform/PlatformPluginTest.java | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index 7c8e8a7c8027d..995715557718a 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -495,9 +495,9 @@ public interface PlatformMessageHandler { /** * The Flutter application would like to restore the visibility of system overlays to the last * set of overlays sent via {@link #showSystemOverlays(List)} or {@link - * #showSystemUiMode(SystemUiMode, List)}. + * #showSystemUiMode(SystemUiMode)}. * - *

If {@link #showSystemOverlays(List)} or {@link #showSystemUiMode(SystemUiMode, List)} has + *

If {@link #showSystemOverlays(List)} or {@link #showSystemUiMode(SystemUiMode)} has * yet to be called, then a default system overlay appearance is desired: * *

{@code View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN } diff --git a/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java b/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java index 15ab5e61d341b..bdb1b11e6ddf5 100644 --- a/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java +++ b/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java @@ -161,7 +161,7 @@ public void setSystemUiMode() { | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN, - fakeActivity.getWindow().getSystemUIVisibility()); + fakeActivity.getWindow().getDecorView().getSystemUiVisibility()); platformPlugin.mPlatformMessageHandler.showSystemUiMode( PlatformChannel.SystemUiMode.IMMERSIVE); @@ -172,7 +172,7 @@ public void setSystemUiMode() { | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN, - fakeActivity.getWindow().getSystemUIVisibility()); + fakeActivity.getWindow().getDecorView().getSystemUiVisibility()); platformPlugin.mPlatformMessageHandler.showSystemUiMode( PlatformChannel.SystemUiMode.IMMERSIVE_STICKY); @@ -183,7 +183,7 @@ public void setSystemUiMode() { | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN, - fakeActivity.getWindow().getSystemUIVisibility()); + fakeActivity.getWindow().getDecorView().getSystemUiVisibility()); platformPlugin.mPlatformMessageHandler.showSystemUiMode( PlatformChannel.SystemUiMode.EDGE_TO_EDGE); @@ -191,7 +191,7 @@ public void setSystemUiMode() { View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, - fakeActivity.getWindow().getSystemUIVisibility()); + fakeActivity.getWindow().getDecorView().getSystemUiVisibility()); } } From 79bca7c27566b2ffc5e671bd29f4610ccfb9127a Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Wed, 23 Jun 2021 16:17:05 -0500 Subject: [PATCH 19/28] Forgot formatting, again. --- .../embedding/engine/systemchannels/PlatformChannel.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index 995715557718a..ff7fdee888d36 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -497,8 +497,8 @@ public interface PlatformMessageHandler { * set of overlays sent via {@link #showSystemOverlays(List)} or {@link * #showSystemUiMode(SystemUiMode)}. * - *

If {@link #showSystemOverlays(List)} or {@link #showSystemUiMode(SystemUiMode)} has - * yet to be called, then a default system overlay appearance is desired: + *

If {@link #showSystemOverlays(List)} or {@link #showSystemUiMode(SystemUiMode)} has yet to + * be called, then a default system overlay appearance is desired: * *

{@code View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN } */ From 01725c418b4f10a678e8d5e0e637ef013c61824c Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Wed, 23 Jun 2021 18:10:55 -0500 Subject: [PATCH 20/28] More docs --- .../embedding/engine/systemchannels/PlatformChannel.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index ff7fdee888d36..6b0a9e2ec0d70 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -462,8 +462,7 @@ public interface PlatformMessageHandler { void showSystemOverlays(@NonNull List overlays); /** - * The Flutter application would like the Android system to display the given {@code mode}, or - * manually configured {@code overlays}. + * The Flutter application would like the Android system to display the given {@code mode}. * *

{@link SystemUiMode#LEAN_BACK} refers to a fullscreen experience that restores system bars * upon tapping anywhere in the application. This tap gesture is not received by the @@ -643,6 +642,10 @@ public enum SystemUiMode { IMMERSIVE_STICKY("SystemUiMode.immersiveSticky"), EDGE_TO_EDGE("SystemUiMode.edgeToEdge"); + /** + * Returns the SystemUiMode for the provied encoded value. @throws NoSuchFieldException if any + * of the given encoded overlay names are invalid. + */ @NonNull static SystemUiMode fromValue(@NonNull String encodedName) throws NoSuchFieldException { for (SystemUiMode mode : SystemUiMode.values()) { @@ -655,6 +658,7 @@ static SystemUiMode fromValue(@NonNull String encodedName) throws NoSuchFieldExc @NonNull private String encodedName; + /** Returens the encoded {@link SystemUiMode} */ SystemUiMode(@NonNull String encodedName) { this.encodedName = encodedName; } From 2b577743fd04341cbd66a70f033be54d9112c881 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Wed, 23 Jun 2021 18:28:10 -0500 Subject: [PATCH 21/28] REview --- .../embedding/engine/systemchannels/PlatformChannel.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index 6b0a9e2ec0d70..7a449b1c9a7dd 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -106,14 +106,14 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result case "SystemChrome.setEnabledSystemUIMode": try { SystemUiMode mode = decodeSystemUiMode((String) arguments); - platformMessageHandler.showSystemUiMode(mode); - result.success(null); } catch (JSONException | NoSuchFieldException exception) { // JSONException: One or more expected fields were either omitted or referenced an // invalid type. // NoSuchFieldException: One or more of the overlay names are invalid. result.error("error", exception.getMessage(), null); } + platformMessageHandler.showSystemUiMode(mode); + result.success(null); break; case "SystemChrome.setSystemUIChangeListener": platformMessageHandler.setSystemUiChangeListener(); From 48f3d70ea061c77ce0a3b7906a27232974139c0c Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Wed, 23 Jun 2021 18:32:41 -0500 Subject: [PATCH 22/28] Put back in try block --- .../embedding/engine/systemchannels/PlatformChannel.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index 7a449b1c9a7dd..6b0a9e2ec0d70 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -106,14 +106,14 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result case "SystemChrome.setEnabledSystemUIMode": try { SystemUiMode mode = decodeSystemUiMode((String) arguments); + platformMessageHandler.showSystemUiMode(mode); + result.success(null); } catch (JSONException | NoSuchFieldException exception) { // JSONException: One or more expected fields were either omitted or referenced an // invalid type. // NoSuchFieldException: One or more of the overlay names are invalid. result.error("error", exception.getMessage(), null); } - platformMessageHandler.showSystemUiMode(mode); - result.success(null); break; case "SystemChrome.setSystemUIChangeListener": platformMessageHandler.setSystemUiChangeListener(); From 10ca900aa275d16550b271e49a5a11e6e25e1cc6 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Wed, 23 Jun 2021 18:45:00 -0500 Subject: [PATCH 23/28] Update build codes for readability --- .../io/flutter/plugin/platform/PlatformPlugin.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index f63893310f8d2..de8b0e87f4040 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -207,7 +207,7 @@ private void setSystemChromeApplicationSwitcherDescription( activity.setTaskDescription( new TaskDescription(description.label, /* icon= */ null, description.color)); } - if (Build.VERSION.SDK_INT >= 28) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { TaskDescription taskDescription = new TaskDescription(description.label, 0, description.color); activity.setTaskDescription(taskDescription); @@ -379,7 +379,7 @@ private void setSystemChromeSystemUIOverlayStyle( window.setStatusBarColor(systemChromeStyle.statusBarColor); } // You can't change the color of the status icons until SDK 23. - if (systemChromeStyle.statusBarIconBrightness != null && Build.VERSION.SDK_INT >= 23) { + if (systemChromeStyle.statusBarIconBrightness != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { switch (systemChromeStyle.statusBarIconBrightness) { case DARK: // View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR @@ -393,7 +393,7 @@ private void setSystemChromeSystemUIOverlayStyle( // You can't override the enforced contrast for a transparent status bar until SDK 29. // This overrides the translucent scrim that may be placed behind the bar on SDK 29+ to ensure // contrast is appropriate when using full screen layout modes like Edge to Edge. - if (!systemChromeStyle.systemStatusBarContrastEnforced && Build.VERSION.SDK_INT >= 29) { + if (!systemChromeStyle.systemStatusBarContrastEnforced && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { window.setStatusBarContrastEnforced(systemChromeStyle.systemStatusBarContrastEnforced); } @@ -408,7 +408,7 @@ private void setSystemChromeSystemUIOverlayStyle( } // You can't change the color of the navigation buttons until SDK 26. if (systemChromeStyle.systemNavigationBarIconBrightness != null - && Build.VERSION.SDK_INT >= 26) { + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { switch (systemChromeStyle.systemNavigationBarIconBrightness) { case DARK: // View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR @@ -420,7 +420,7 @@ private void setSystemChromeSystemUIOverlayStyle( } } // You can't change the color of the navigation bar divider color until SDK 28. - if (systemChromeStyle.systemNavigationBarDividerColor != null && Build.VERSION.SDK_INT >= 28) { + if (systemChromeStyle.systemNavigationBarDividerColor != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); window.setNavigationBarDividerColor(systemChromeStyle.systemNavigationBarDividerColor); @@ -430,7 +430,7 @@ private void setSystemChromeSystemUIOverlayStyle( // This overrides the translucent scrim that may be placed behind 2/3 button navigation bars on // SDK 29+ to ensure contrast is appropriate when using full screen layout modes like // Edge to Edge. - if (!systemChromeStyle.systemNavigationBarContrastEnforced && Build.VERSION.SDK_INT >= 29) { + if (!systemChromeStyle.systemNavigationBarContrastEnforced && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { window.setNavigationBarContrastEnforced( systemChromeStyle.systemNavigationBarContrastEnforced); } From 2a4fba5a0270f41662e308e69ce06ec5754d97a2 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Wed, 23 Jun 2021 18:45:50 -0500 Subject: [PATCH 24/28] Once more with feeling --- .../io/flutter/plugin/platform/PlatformPlugin.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index de8b0e87f4040..e7e27ecf5b654 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -379,7 +379,8 @@ private void setSystemChromeSystemUIOverlayStyle( window.setStatusBarColor(systemChromeStyle.statusBarColor); } // You can't change the color of the status icons until SDK 23. - if (systemChromeStyle.statusBarIconBrightness != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (systemChromeStyle.statusBarIconBrightness != null + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { switch (systemChromeStyle.statusBarIconBrightness) { case DARK: // View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR @@ -393,7 +394,8 @@ private void setSystemChromeSystemUIOverlayStyle( // You can't override the enforced contrast for a transparent status bar until SDK 29. // This overrides the translucent scrim that may be placed behind the bar on SDK 29+ to ensure // contrast is appropriate when using full screen layout modes like Edge to Edge. - if (!systemChromeStyle.systemStatusBarContrastEnforced && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (!systemChromeStyle.systemStatusBarContrastEnforced + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { window.setStatusBarContrastEnforced(systemChromeStyle.systemStatusBarContrastEnforced); } @@ -420,7 +422,8 @@ private void setSystemChromeSystemUIOverlayStyle( } } // You can't change the color of the navigation bar divider color until SDK 28. - if (systemChromeStyle.systemNavigationBarDividerColor != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + if (systemChromeStyle.systemNavigationBarDividerColor != null + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); window.setNavigationBarDividerColor(systemChromeStyle.systemNavigationBarDividerColor); @@ -430,7 +433,8 @@ private void setSystemChromeSystemUIOverlayStyle( // This overrides the translucent scrim that may be placed behind 2/3 button navigation bars on // SDK 29+ to ensure contrast is appropriate when using full screen layout modes like // Edge to Edge. - if (!systemChromeStyle.systemNavigationBarContrastEnforced && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (!systemChromeStyle.systemNavigationBarContrastEnforced + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { window.setNavigationBarContrastEnforced( systemChromeStyle.systemNavigationBarContrastEnforced); } From 0dfd290b5b8bdc2485842ec23fd6ce7f03131bd9 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Thu, 24 Jun 2021 11:54:28 -0500 Subject: [PATCH 25/28] Revert build codes change --- .../flutter/plugin/platform/PlatformPlugin.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index e7e27ecf5b654..f63893310f8d2 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -207,7 +207,7 @@ private void setSystemChromeApplicationSwitcherDescription( activity.setTaskDescription( new TaskDescription(description.label, /* icon= */ null, description.color)); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + if (Build.VERSION.SDK_INT >= 28) { TaskDescription taskDescription = new TaskDescription(description.label, 0, description.color); activity.setTaskDescription(taskDescription); @@ -379,8 +379,7 @@ private void setSystemChromeSystemUIOverlayStyle( window.setStatusBarColor(systemChromeStyle.statusBarColor); } // You can't change the color of the status icons until SDK 23. - if (systemChromeStyle.statusBarIconBrightness != null - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (systemChromeStyle.statusBarIconBrightness != null && Build.VERSION.SDK_INT >= 23) { switch (systemChromeStyle.statusBarIconBrightness) { case DARK: // View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR @@ -394,8 +393,7 @@ private void setSystemChromeSystemUIOverlayStyle( // You can't override the enforced contrast for a transparent status bar until SDK 29. // This overrides the translucent scrim that may be placed behind the bar on SDK 29+ to ensure // contrast is appropriate when using full screen layout modes like Edge to Edge. - if (!systemChromeStyle.systemStatusBarContrastEnforced - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (!systemChromeStyle.systemStatusBarContrastEnforced && Build.VERSION.SDK_INT >= 29) { window.setStatusBarContrastEnforced(systemChromeStyle.systemStatusBarContrastEnforced); } @@ -410,7 +408,7 @@ private void setSystemChromeSystemUIOverlayStyle( } // You can't change the color of the navigation buttons until SDK 26. if (systemChromeStyle.systemNavigationBarIconBrightness != null - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + && Build.VERSION.SDK_INT >= 26) { switch (systemChromeStyle.systemNavigationBarIconBrightness) { case DARK: // View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR @@ -422,8 +420,7 @@ private void setSystemChromeSystemUIOverlayStyle( } } // You can't change the color of the navigation bar divider color until SDK 28. - if (systemChromeStyle.systemNavigationBarDividerColor != null - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + if (systemChromeStyle.systemNavigationBarDividerColor != null && Build.VERSION.SDK_INT >= 28) { window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); window.setNavigationBarDividerColor(systemChromeStyle.systemNavigationBarDividerColor); @@ -433,8 +430,7 @@ private void setSystemChromeSystemUIOverlayStyle( // This overrides the translucent scrim that may be placed behind 2/3 button navigation bars on // SDK 29+ to ensure contrast is appropriate when using full screen layout modes like // Edge to Edge. - if (!systemChromeStyle.systemNavigationBarContrastEnforced - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (!systemChromeStyle.systemNavigationBarContrastEnforced && Build.VERSION.SDK_INT >= 29) { window.setNavigationBarContrastEnforced( systemChromeStyle.systemNavigationBarContrastEnforced); } From efec6901f60c328dc8dad26d46c56b91a6a91ab5 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Mon, 28 Jun 2021 16:36:45 -0500 Subject: [PATCH 26/28] Fix for revert --- .../plugin/platform/PlatformPlugin.java | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index f63893310f8d2..cc007dd2dbe52 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -370,15 +370,12 @@ private void setSystemChromeSystemUIOverlayStyle( int flags = view.getSystemUiVisibility(); // SYSTEM STATUS BAR ------------------------------------------------------------------- - // You can't change the color of the system status bar until SDK 21. + // You can't change the color of the system status bar until SDK 21, but you can't change the + // color of the status icons until SDK 23. We only allow both starting at 23 to ensure buttons + // and icons can be visible when changing the background color. // If transparent, SDK 29 and higher may apply a translucent scrim behind the bar to ensure // proper contrast. This can be overridden with // SystemChromeStyle.systemStatusBarContrastEnforced. - if (systemChromeStyle.statusBarColor != null - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - window.setStatusBarColor(systemChromeStyle.statusBarColor); - } - // You can't change the color of the status icons until SDK 23. if (systemChromeStyle.statusBarIconBrightness != null && Build.VERSION.SDK_INT >= 23) { switch (systemChromeStyle.statusBarIconBrightness) { case DARK: @@ -389,6 +386,11 @@ private void setSystemChromeSystemUIOverlayStyle( flags &= ~0x2000; break; } + + if (systemChromeStyle.statusBarColor != null + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + window.setStatusBarColor(systemChromeStyle.statusBarColor); + } } // You can't override the enforced contrast for a transparent status bar until SDK 29. // This overrides the translucent scrim that may be placed behind the bar on SDK 29+ to ensure @@ -398,15 +400,12 @@ private void setSystemChromeSystemUIOverlayStyle( } // SYSTEM NAVIGATION BAR -------------------------------------------------------------- - // You can't change the color of the system navigation bar until SDK 21. + // You can't change the color of the system navigation bar until SDK 21, but you can't change + // the color of the navigation buttons until SDK 26. We only allow both starting at 23 to + // ensure buttons can be visible when changing the background color. // If transparent, SDK 29 and higher may apply a translucent scrim behind 2/3 button navigation // bars to ensure proper contrast. This can be overridden with // SystemChromeStyle.systemNavigationBarContrastEnforced. - if (systemChromeStyle.systemNavigationBarColor != null - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - window.setNavigationBarColor(systemChromeStyle.systemNavigationBarColor); - } - // You can't change the color of the navigation buttons until SDK 26. if (systemChromeStyle.systemNavigationBarIconBrightness != null && Build.VERSION.SDK_INT >= 26) { switch (systemChromeStyle.systemNavigationBarIconBrightness) { @@ -418,6 +417,10 @@ private void setSystemChromeSystemUIOverlayStyle( flags &= ~0x10; break; } + + if (systemChromeStyle.systemNavigationBarColor != null) { + window.setNavigationBarColor(systemChromeStyle.systemNavigationBarColor); + } } // You can't change the color of the navigation bar divider color until SDK 28. if (systemChromeStyle.systemNavigationBarDividerColor != null && Build.VERSION.SDK_INT >= 28) { From 0f31f8bf4debcdf977d030871dca41ffe0792ee4 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Mon, 28 Jun 2021 16:41:01 -0500 Subject: [PATCH 27/28] ++ --- .../android/io/flutter/plugin/platform/PlatformPlugin.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index cc007dd2dbe52..c510d2f1690b4 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -387,8 +387,7 @@ private void setSystemChromeSystemUIOverlayStyle( break; } - if (systemChromeStyle.statusBarColor != null - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (systemChromeStyle.statusBarColor != null) { window.setStatusBarColor(systemChromeStyle.statusBarColor); } } From 74c0931f6165914a0b12826ec3ba1bc6bccb2435 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Mon, 28 Jun 2021 19:26:56 -0500 Subject: [PATCH 28/28] Review feedback --- .../android/io/flutter/plugin/platform/PlatformPlugin.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index c510d2f1690b4..cc3cb2a7ff0b8 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -370,7 +370,7 @@ private void setSystemChromeSystemUIOverlayStyle( int flags = view.getSystemUiVisibility(); // SYSTEM STATUS BAR ------------------------------------------------------------------- - // You can't change the color of the system status bar until SDK 21, but you can't change the + // You can't change the color of the system status bar until SDK 21, and you can't change the // color of the status icons until SDK 23. We only allow both starting at 23 to ensure buttons // and icons can be visible when changing the background color. // If transparent, SDK 29 and higher may apply a translucent scrim behind the bar to ensure @@ -399,8 +399,8 @@ private void setSystemChromeSystemUIOverlayStyle( } // SYSTEM NAVIGATION BAR -------------------------------------------------------------- - // You can't change the color of the system navigation bar until SDK 21, but you can't change - // the color of the navigation buttons until SDK 26. We only allow both starting at 23 to + // You can't change the color of the system navigation bar until SDK 21, and you can't change + // the color of the navigation buttons until SDK 26. We only allow both starting at 26 to // ensure buttons can be visible when changing the background color. // If transparent, SDK 29 and higher may apply a translucent scrim behind 2/3 button navigation // bars to ensure proper contrast. This can be overridden with