|
4 | 4 | import android.graphics.Color; |
5 | 5 | import android.os.Build; |
6 | 6 | import android.util.DisplayMetrics; |
| 7 | +import android.util.TypedValue; |
7 | 8 | import android.view.View; |
8 | 9 | import android.view.Window; |
9 | 10 | import android.view.WindowInsets; |
10 | 11 | import android.view.WindowManager; |
11 | 12 | import androidx.appcompat.app.AppCompatActivity; |
| 13 | +import androidx.core.graphics.ColorUtils; |
12 | 14 | import androidx.core.view.ViewCompat; |
13 | 15 | import androidx.core.view.WindowCompat; |
14 | 16 | import androidx.core.view.WindowInsetsCompat; |
@@ -63,11 +65,20 @@ public void updateStyle() { |
63 | 65 |
|
64 | 66 | public void setBackgroundColor(int color) { |
65 | 67 | Window window = activity.getWindow(); |
66 | | - clearTranslucentStatusFlagDeprecated(); |
67 | | - window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); |
68 | | - setStatusBarColorDeprecated(color); |
69 | | - // update the local color field as well |
70 | | - currentStatusBarColor = color; |
| 68 | + if (shouldSetStatusBarColor(isEdgeToEdgeOptOutEnabled(window))) { |
| 69 | + clearTranslucentStatusFlagDeprecated(); |
| 70 | + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); |
| 71 | + setStatusBarColorDeprecated(color); |
| 72 | + currentStatusBarColor = color; |
| 73 | + |
| 74 | + // only set foreground color if style is default |
| 75 | + if (currentStyle.equals("DEFAULT")) { |
| 76 | + // determine if the color is light or dark using luminance and set icon color |
| 77 | + boolean isLightColor = ColorUtils.calculateLuminance(color) > 0.5; |
| 78 | + WindowInsetsControllerCompat insetsController = WindowCompat.getInsetsController(window, window.getDecorView()); |
| 79 | + insetsController.setAppearanceLightStatusBars(isLightColor); |
| 80 | + } |
| 81 | + } |
71 | 82 | } |
72 | 83 |
|
73 | 84 | public void hide() { |
@@ -107,6 +118,29 @@ public void setOverlaysWebView(Boolean overlays) { |
107 | 118 | listener.onChange(statusBarOverlayChanged, getInfo()); |
108 | 119 | } |
109 | 120 |
|
| 121 | + private boolean shouldSetStatusBarColor(boolean hasOptOut) { |
| 122 | + boolean canSetStatusBar; |
| 123 | + int deviceApi = Build.VERSION.SDK_INT; |
| 124 | + if (deviceApi < Build.VERSION_CODES.VANILLA_ICE_CREAM) { |
| 125 | + // device below Android 15 - can always set status bar |
| 126 | + canSetStatusBar = true; |
| 127 | + } else if (deviceApi == Build.VERSION_CODES.VANILLA_ICE_CREAM) { |
| 128 | + canSetStatusBar = hasOptOut; // app targets 15 - can set status bar if opted out |
| 129 | + } else { |
| 130 | + canSetStatusBar = false; // app targets 16 - opt-out ignored or app targets 15 but there is not opt out |
| 131 | + } |
| 132 | + return canSetStatusBar; |
| 133 | + } |
| 134 | + |
| 135 | + private boolean isEdgeToEdgeOptOutEnabled(Window window) { |
| 136 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { |
| 137 | + TypedValue value = new TypedValue(); |
| 138 | + window.getContext().getTheme().resolveAttribute(android.R.attr.windowOptOutEdgeToEdgeEnforcement, value, true); |
| 139 | + return value.data != 0; // value is set to -1 on true as of Android 15, so we have to do this. |
| 140 | + } |
| 141 | + return false; |
| 142 | + } |
| 143 | + |
110 | 144 | private boolean getIsOverlaid() { |
111 | 145 | return ( |
112 | 146 | (getSystemUiVisibilityDeprecated(activity.getWindow().getDecorView()) & getSystemUiFlagLayoutFullscreenDeprecated()) == |
|
0 commit comments