I've just setup Edge2Edge mode on a new Android project. Generally that works fine, however on app startup there's a noticable moment where the status bar is not visible at all.
I have two issues here:
a) The status bar is "flickering" as it's first shown, then not shown, then shown again.
b) The status bar color is close to the white app background, but not completely white.
This is how MainActivity
looks like:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
NewToGetThemesTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize().safeDrawingPadding(),
color = MaterialTheme.colorScheme.background,
) {
Greeting("Android")
}
}
}
}
}
Theme.kt
looks like this (note the commented out side effect):
private val DarkColorScheme = darkColorScheme(
primary = Purple80,
secondary = PurpleGrey80,
tertiary = Pink80
)
private val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40
/* Other default colors to override
background = Color(0xFFFFFBFE),
surface = Color(0xFFFFFBFE),
onPrimary = Color.White,
onSecondary = Color.White,
onTertiary = Color.White,
onBackground = Color(0xFF1C1B1F),
onSurface = Color(0xFF1C1B1F),
*/
)
@Composable
fun NewToGetThemesTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as Activity).window
// I've commented out the next lines as they made everything worse
//window.statusBarColor = colorScheme.primary.toArgb()
//WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
}
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}
themes.xml
looks like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.NewToGetThemes" parent="android:Theme.Material.Light.NoActionBar" />
</resources>
What you see is due to the Activity theming applied through the manifest.
If you remove the enableEdgeToEdge()
call, you can see how your app would look like with the XML theme applied:
As you can see, the status bar content is white because its background is dark.
Now, if you have the enableEdgeToEdge()
call, it internally sets the background color of the status bar to transparent and the content color is set to dark. What you don't see is that before the content color can be applied, the XML values take over thinking it should be a white content color due to the dark background. So the "flickering" happens because of the content first being set to light, then to dark, in the following order:
enableEdgeToEdge()
called - status bar content turns darkIf this bothers you much, it can be easily fixed by setting the android:windowLightStatusBar
value to true
in the theme:
<style name="Theme.NewToGetThemes" parent="android:Theme.Material.Light.NoActionBar" />
<item name="android:windowLightStatusBar">true</item>
</style>
This tells the system that the status bar background is light colored, which means its content should be dark.
Note that if you plan on using a dark theme as well (highly recommended), you'll need to create the appropriate version of this theme in the
values-night
folder with itsparent
set toandroid:Theme.Material.NoActionBar
(note the lack ofLight
), and theandroid:windowLightStatusBar
value tofalse
.
As for the second issue of "The status bar color is close to the white app background, but not completely white.": it's actually your background which is likely off-white. If you check out your Theme.kt file, you'll see that only a very few parameters of the theme are set, and there's the background
one commented out, which probably shows the default whitish background color (#FFFBFE):
background = Color(0xFFFFFBFE)
Though you haven't asked about it, I'd recommend either using a Scaffold
as the base instead of a Surface
or setting the safeDrawingPadding()
modifier on the internal components of the Surface
, otherwise the background behind the status bar will be the default (XML) theme one, while the app background will come from the compose theme.
The Scaffold
internally manages window insets so it spans the entire window. Besides that, it already applies the theme background color to the container so you don't need to set it manually.