I'm trying to create a launcher app, but i had problem when trying to change windowLightStatusBar
programmatically on API 30 and the same code works perfectly fine bellow that, i hope if someone can help me out:)
Here is the full class source code:
public final class AppDrawer extends BottomSheetBehavior.BottomSheetCallback implements OnApplyWindowInsetsListener {
private static boolean ALREADY_CREATED = false;
private AppCompatActivity activity;
private boolean dragging = false;
private float radius;
private int left, right, height, peekOver, oldState;
private Rect displayRect = new Rect();
private DisplayMetrics displayMetrics = new DisplayMetrics();
private Insets navigationBarInsets = Insets.of(0, 0, 0, 0), cutoutInsets = navigationBarInsets;
private WindowInsetsControllerCompat windowInsetsController;
private Configuration oldConfiguration;
private CardView cardView;
private FrameLayout frameLayout;
private BottomSheetBehavior<FrameLayout> bottomSheetBehavior;
public AppDrawer(AppCompatActivity activity){
if(ALREADY_CREATED) throw new IllegalArgumentException("The appDrawer object cannot be created more than once, clear the existing one from the memory first.");
this.activity = activity;
ALREADY_CREATED = true;
}
public void destroy(){
activity = null;
radius = 0.0f;
left = right = height = peekOver = oldState = 0;
displayRect = null;
displayMetrics = null;
navigationBarInsets = cutoutInsets = navigationBarInsets = null;
windowInsetsController = null;
oldConfiguration = null;
cardView = null;
frameLayout = null;
bottomSheetBehavior = null;
ALREADY_CREATED = false;
}
// WindowInsetControllerCompat is created and set from the activity that created this class
public void setWindowInsetsController(@NonNull WindowInsetsControllerCompat windowInsetsController) { this.windowInsetsController = windowInsetsController; }
public void initViews(View contentView){
oldConfiguration = activity.getResources().getConfiguration();
cardView = activity.findViewById(R.id.app_drawer_card_view);
frameLayout = activity.findViewById(R.id.app_drawer_container);
bottomSheetBehavior = BottomSheetBehavior.from(frameLayout);
bottomSheetBehavior.addBottomSheetCallback(this);
ViewCompat.setOnApplyWindowInsetsListener(contentView, this);
updateVars();
}
@Override
public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
if(dragging) return insets;
cutoutInsets = insets.getInsets(WindowInsetsCompat.Type.displayCutout());
navigationBarInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars());
updateVars();
if(bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED) frameLayout.setPadding(left + navigationBarInsets.left, 0, right + navigationBarInsets.right, 0);
return insets;
}
public void setConfiguration(Configuration configuration) { this.oldConfiguration = configuration; }
private void updateWindowInsetsBars(int state){
// here is the one i used
if (state != BottomSheetBehavior.STATE_COLLAPSED && (oldConfiguration.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_NO) {
windowInsetsController.setAppearanceLightNavigationBars(true);
windowInsetsController.setAppearanceLightStatusBars(true);
} else {
windowInsetsController.setAppearanceLightNavigationBars(false);
windowInsetsController.setAppearanceLightStatusBars(false);
}
// here is the one of @Zain answer
if (state != BottomSheetBehavior.STATE_COLLAPSED && (oldConfiguration.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_NO) {
new WindowInsetsControllerCompat(activity.getWindow(), activity.getWindow().getDecorView()).setAppearanceLightStatusBars(true);
new WindowInsetsControllerCompat(activity.getWindow(), activity.getWindow().getDecorView()).setAppearanceLightNavigationBars(true);
} else {
new WindowInsetsControllerCompat(activity.getWindow(), activity.getWindow().getDecorView()).setAppearanceLightStatusBars(false);
new WindowInsetsControllerCompat(activity.getWindow(), activity.getWindow().getDecorView()).setAppearanceLightNavigationBars(false);
}
}
private void updateCardViewState(float slideOffset){
float a = 1.f - slideOffset;
cardView.setRadius(radius * a);
frameLayout.setPadding((int) ((left + navigationBarInsets.left) * a) , 0, (int) ((right + navigationBarInsets.right) * a), 0);
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) cardView.getLayoutParams();
layoutParams.height = (int) ((displayRect.height() + navigationBarInsets.bottom + cutoutInsets.top + cutoutInsets.bottom) * slideOffset + height * a);
Log.d("AppDrawer", "card height: " + layoutParams.height + ", screen height: " + displayRect.height());
//cardView.setAlpha(Math.min(slideOffset * 1.1f, 1.0f));
cardView.setLayoutParams(layoutParams);
}
private void updateDisplayMetrics(){
WindowManager windowManager = this.activity.getWindowManager();
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
displayRect.set(windowManager.getCurrentWindowMetrics().getBounds());
displayRect.bottom -= navigationBarInsets.bottom + cutoutInsets.top + cutoutInsets.bottom;
displayRect.right -= navigationBarInsets.right + cutoutInsets.left + cutoutInsets.right;
} else {
displayRect.top = 0;
displayRect.bottom = displayMetrics.heightPixels;
displayRect.left = 0;
displayRect.right = displayMetrics.widthPixels;
}
}
private void updateVars(){
updateDisplayMetrics();
peekOver = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10f, displayMetrics);
radius = radius == 0 ? cardView.getRadius() : radius;
left = left == 0 ? frameLayout.getPaddingLeft() : left;
right = right == 0 ? frameLayout.getPaddingRight() : right;
height = height == 0 ? cardView.getLayoutParams().height : height;
bottomSheetBehavior.setPeekHeight(height + navigationBarInsets.bottom + peekOver);
if(oldState != 0) updateCardViewState(oldState == BottomSheetBehavior.STATE_COLLAPSED ? 0.0f : 1.0f);
}
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
dragging = newState == BottomSheetBehavior.STATE_DRAGGING;
updateWindowInsetsBars(newState);
oldState = newState;
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) { updateCardViewState(slideOffset); }
}
Here you can see on API 30 that the navigationbar
is white while the statusbar
still black, even tho both are set to false
but it doesn't effect the statusbar
at all.
But here on API 29 (it works fine below that too) that they are both changes fine.
It is a platform bug. https://issuetracker.google.com/issues/180881870
To fix this issue you should just update your androidx.core:core-ktx
to version 1.8.0-alpha03
or higher.
Pls refer to api changes for details https://developer.android.com/jetpack/androidx/releases/core#1.8.0-alpha03