Skip to content

Commit 1a91e68

Browse files
drchenafohrman
authored andcommitted
[BottomSheet] Fix bottom sheet dialog status bar color adjustment
This CL fixes two issues regarding bottom sheet dialog status color adjustment in edge-to-edge mode: 1. Uses WindowInsetsControllerCompat to set status bar color to replace the deprecated way of setting flags, which cannot override the light/dark setting set by WindowInsetsControllerCompat. 2. Tracks Window change so the original status bar color can be updated when the dialog is re-shown. (The day/night mode can be changed when the dialog is hidden.) Resolves #2168 PiperOrigin-RevId: 450463570
1 parent 21f9b0f commit 1a91e68

File tree

2 files changed

+68
-33
lines changed

2 files changed

+68
-33
lines changed

lib/java/com/google/android/material/bottomsheet/BottomSheetDialog.java

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,14 @@
1818

1919
import com.google.android.material.R;
2020

21-
import static android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
2221
import static com.google.android.material.color.MaterialColors.isColorLight;
22+
import static com.google.android.material.internal.EdgeToEdgeUtils.setLightStatusBar;
2323

2424
import android.content.Context;
2525
import android.content.res.ColorStateList;
2626
import android.content.res.TypedArray;
2727
import android.graphics.Color;
2828
import android.graphics.drawable.ColorDrawable;
29-
import android.os.Build;
3029
import android.os.Build.VERSION;
3130
import android.os.Build.VERSION_CODES;
3231
import android.os.Bundle;
@@ -46,9 +45,10 @@
4645
import androidx.core.view.AccessibilityDelegateCompat;
4746
import androidx.core.view.OnApplyWindowInsetsListener;
4847
import androidx.core.view.ViewCompat;
48+
import androidx.core.view.WindowCompat;
4949
import androidx.core.view.WindowInsetsCompat;
50+
import androidx.core.view.WindowInsetsControllerCompat;
5051
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
51-
import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback;
5252
import com.google.android.material.shape.MaterialShapeDrawable;
5353

5454
/**
@@ -77,7 +77,7 @@ public class BottomSheetDialog extends AppCompatDialog {
7777
boolean cancelable = true;
7878
private boolean canceledOnTouchOutside = true;
7979
private boolean canceledOnTouchOutsideSet;
80-
private BottomSheetCallback edgeToEdgeCallback;
80+
private EdgeToEdgeCallback edgeToEdgeCallback;
8181
private boolean edgeToEdgeEnabled;
8282

8383
public BottomSheetDialog(@NonNull Context context) {
@@ -193,6 +193,16 @@ public void onAttachedToWindow() {
193193
window.getDecorView().setSystemUiVisibility(edgeToEdgeFlags);
194194
}
195195
}
196+
if (edgeToEdgeCallback != null) {
197+
edgeToEdgeCallback.setWindow(window);
198+
}
199+
}
200+
}
201+
202+
@Override
203+
public void onDetachedFromWindow() {
204+
if (edgeToEdgeCallback != null) {
205+
edgeToEdgeCallback.setWindow(null);
196206
}
197207
}
198208

@@ -301,6 +311,7 @@ public WindowInsetsCompat onApplyWindowInsets(View view, WindowInsetsCompat inse
301311

302312
if (insets != null) {
303313
edgeToEdgeCallback = new EdgeToEdgeCallback(bottomSheet, insets);
314+
edgeToEdgeCallback.setWindow(getWindow());
304315
behavior.addBottomSheetCallback(edgeToEdgeCallback);
305316
}
306317

@@ -409,16 +420,15 @@ public void onSlide(@NonNull View bottomSheet, float slideOffset) {}
409420

410421
private static class EdgeToEdgeCallback extends BottomSheetBehavior.BottomSheetCallback {
411422

412-
private final boolean lightBottomSheet;
413-
private final boolean lightStatusBar;
414-
private final WindowInsetsCompat insetsCompat;
423+
@Nullable private final Boolean lightBottomSheet;
424+
@NonNull private final WindowInsetsCompat insetsCompat;
425+
426+
@Nullable private Window window;
427+
private boolean lightStatusBar;
415428

416429
private EdgeToEdgeCallback(
417430
@NonNull final View bottomSheet, @NonNull WindowInsetsCompat insetsCompat) {
418431
this.insetsCompat = insetsCompat;
419-
lightStatusBar =
420-
VERSION.SDK_INT >= VERSION_CODES.M
421-
&& (bottomSheet.getSystemUiVisibility() & SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0;
422432

423433
// Try to find the background color to automatically change the status bar icons so they will
424434
// still be visible when the bottomsheet slides underneath the status bar.
@@ -438,7 +448,7 @@ private EdgeToEdgeCallback(
438448
lightBottomSheet = isColorLight(((ColorDrawable) bottomSheet.getBackground()).getColor());
439449
} else {
440450
// Otherwise don't change the status bar color
441-
lightBottomSheet = lightStatusBar;
451+
lightBottomSheet = null;
442452
}
443453
}
444454

@@ -457,11 +467,25 @@ void onLayout(@NonNull View bottomSheet) {
457467
setPaddingForPosition(bottomSheet);
458468
}
459469

470+
void setWindow(@Nullable Window window) {
471+
if (this.window == window) {
472+
return;
473+
}
474+
this.window = window;
475+
if (window != null) {
476+
WindowInsetsControllerCompat insetsController =
477+
WindowCompat.getInsetsController(window, window.getDecorView());
478+
lightStatusBar = insetsController.isAppearanceLightStatusBars();
479+
}
480+
}
481+
460482
private void setPaddingForPosition(View bottomSheet) {
461483
if (bottomSheet.getTop() < insetsCompat.getSystemWindowInsetTop()) {
462484
// If the bottomsheet is light, we should set light status bar so the icons are visible
463485
// since the bottomsheet is now under the status bar.
464-
setLightStatusBar(bottomSheet, lightBottomSheet);
486+
if (window != null) {
487+
setLightStatusBar(window, lightBottomSheet == null ? lightStatusBar : lightBottomSheet);
488+
}
465489
// Smooth transition into status bar when drawing edge to edge.
466490
bottomSheet.setPadding(
467491
bottomSheet.getPaddingLeft(),
@@ -471,7 +495,9 @@ private void setPaddingForPosition(View bottomSheet) {
471495
} else if (bottomSheet.getTop() != 0) {
472496
// Reset the status bar icons to the original color because the bottomsheet is not under the
473497
// status bar.
474-
setLightStatusBar(bottomSheet, lightStatusBar);
498+
if (window != null) {
499+
setLightStatusBar(window, lightStatusBar);
500+
}
475501
bottomSheet.setPadding(
476502
bottomSheet.getPaddingLeft(),
477503
0,
@@ -480,16 +506,4 @@ private void setPaddingForPosition(View bottomSheet) {
480506
}
481507
}
482508
}
483-
484-
public static void setLightStatusBar(@NonNull View view, boolean isLight) {
485-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
486-
int flags = view.getSystemUiVisibility();
487-
if (isLight) {
488-
flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
489-
} else {
490-
flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
491-
}
492-
view.setSystemUiVisibility(flags);
493-
}
494-
}
495509
}

lib/java/com/google/android/material/internal/EdgeToEdgeUtils.java

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,18 +102,39 @@ public static void applyEdgeToEdge(
102102
window.setStatusBarColor(statusBarColor);
103103
window.setNavigationBarColor(navigationBarColor);
104104

105-
boolean isLightStatusBar =
106-
isUsingLightSystemBar(statusBarColor, isColorLight(statusBarOverlapBackgroundColor));
107-
boolean isLightNavigationBar =
105+
setLightStatusBar(
106+
window,
107+
isUsingLightSystemBar(statusBarColor, isColorLight(statusBarOverlapBackgroundColor)));
108+
setLightNavigationBar(
109+
window,
108110
isUsingLightSystemBar(
109-
navigationBarColor, isColorLight(navigationBarOverlapBackgroundColor));
111+
navigationBarColor, isColorLight(navigationBarOverlapBackgroundColor)));
112+
}
110113

114+
/**
115+
* Changes the foreground color of the status bars to light or dark so that the items on the bar
116+
* can be read clearly.
117+
*
118+
* @param window Window that hosts the status bars
119+
* @param isLight {@code true} to make the foreground color light
120+
*/
121+
public static void setLightStatusBar(@NonNull Window window, boolean isLight) {
111122
WindowInsetsControllerCompat insetsController =
112123
WindowCompat.getInsetsController(window, window.getDecorView());
113-
if (insetsController != null) {
114-
insetsController.setAppearanceLightStatusBars(isLightStatusBar);
115-
insetsController.setAppearanceLightNavigationBars(isLightNavigationBar);
116-
}
124+
insetsController.setAppearanceLightStatusBars(isLight);
125+
}
126+
127+
/**
128+
* Changes the foreground color of the navigation bars to light or dark so that the items on the
129+
* bar can be read clearly.
130+
*
131+
* @param window Window that hosts the status bars
132+
* @param isLight {@code true} to make the foreground color light.
133+
*/
134+
public static void setLightNavigationBar(@NonNull Window window, boolean isLight) {
135+
WindowInsetsControllerCompat insetsController =
136+
WindowCompat.getInsetsController(window, window.getDecorView());
137+
insetsController.setAppearanceLightNavigationBars(isLight);
117138
}
118139

119140
@TargetApi(VERSION_CODES.LOLLIPOP)

0 commit comments

Comments
 (0)