Issue
I use NavHostFragment
with BottomNavigationView
with 5 tabs and fitsSystemWindows="true"
.
Description:
App has different app bar design for each fragment. For example, in 1st fragment app bar contains CollapsingToolbarLayout
with background image which is drawn under status bar, and in 2nd fragment app bar contains only Toolbar
and nothing is drawn under status bar. But to make UI not jumpy I just set all fragments layout to use fitsSystemWindows="true"
.
In first case, status bar background needs to be transparent to make image visible and it's icon's color should be white. But in the 2nd fragment app bar and status bar are white and icon's color should be dark.
I was using these two methods below to change status bar settings when switching between fragments.
private fun setStatusBarBackgroundColor(colorId: Int) {
window.statusBarColor = ContextCompat.getColor(this, colorId)
}
@RequiresApi(Build.VERSION_CODES.M)
private fun setStatusBarIconsColor(isDark: Boolean) { // this is causing the issue
val oldFlags = window.decorView.systemUiVisibility
var newFlags = oldFlags
newFlags = if (isDark) {
newFlags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
} else {
newFlags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
}
if (newFlags != oldFlags) window.decorView.systemUiVisibility = newFlags
}
Problem:
However, on android Oreo and lower (23 >= API <= 27) I noticed that when navigating between fragments any of them can become blank at any time. After that, all of the next destinations (even navigating back) are blank as well. Only BottomNavigationView
is visible and content of NavHostFragment
is just blank. But in the logcat I see that fragments are created and data fetching is done, etc. No errors logs though
Prior to blank fragments if I swipe down to activate SwipeRefreshLayout
and while it is refreshing I try to scroll, CollapsingToolbarLayout
starts to behave very strangely. Scroll events won't be passed to RecyclerView
until CollapsingToolbarLayout
fully collapsed. Then RecyclerView
will start to scroll but its content won't be drawn on all available vertical space but be hidden on top as if CollapsingToolbarLayout
was expanded.
Removing invocation of method with SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
solves the problem. But I need to toggle the color of status bar icons.
Solution
Android team added new API to make working with Window APIs easier. I'm not sure which version of core library has them but I believe starting from 1.5.0 these APIs are available. I'm using androidx.core:core-ktx:1.6.0
.
Now setAppearanceLightStatusBars(boolean isLight)
from InsetsController class allows to easily change the appearance of icons in status bar in runtime.
Solution:
WindowCompat.getInsetsController(window, window.decorView)?.isAppearanceLightStatusBars = isLightStatusBar
NOTE: on API 30 and later, calling this method has NO Effect if app has specified <item name="android:windowLightStatusBar">true/false</item>
in the AppTheme
in styles.xml. To be able to toggle status bar icons' color in runtime on API 30+, remove android:windowLightStatusBar
from AppTheme
Under the hood, this method has 2 different implementations depending on Android OS version.
Internal implementation for API 23-29:
// internal method
public void setAppearanceLightStatusBars(boolean isLight) {
if (isLight) {
unsetWindowFlag(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
setWindowFlag(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
setSystemUiFlag(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
unsetSystemUiFlag(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
}
Internal implementation for for API 30 and later:
// internal method
public void setAppearanceLightStatusBars(boolean isLight) {
if (isLight) {
mInsetsController.setSystemBarsAppearance(
WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS,
WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS);
} else {
mInsetsController.setSystemBarsAppearance(
0,
WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS);
}
}
Answered By - Marat
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.