Nurseyit Tursunkulov
Nurseyit Tursunkulov

Reputation: 9380

how to change statusbar color in jetpack compose?

how to make status bar color transparent in compose like here:

enter image description here

it has the same color but with a little bit shade.

Upvotes: 84

Views: 101946

Answers (26)

Cristan
Cristan

Reputation: 14085

Just go for the old-fashioned way and add this to themes.xml:

<item name="android:windowTranslucentStatus">true</item>

-edit: this no longer works in Android 15+ in combination with target SDK is 35+. And with reason: you're supposed to design your app edge-to-edge now.

Upvotes: 18

Rafay Rao
Rafay Rao

Reputation: 51

In your Theme.kt class you will find the below code

SideEffect {
        val window = (view.context as Activity).window
        window.statusBarColor = colorScheme.primary.toArgb()
        WindowCompat.getInsetsController(window, 
        view).isAppearanceLightStatusBars = darkTheme
       }
        }

just change the
window.statusBarColor = colorScheme.primary.toArgb() to your desired color like

window.statusBarColor = Color.Black.toArgb()

and you are done with changing your status bar color. Happy Coding :)

Upvotes: 0

Nurseyit Tursunkulov
Nurseyit Tursunkulov

Reputation: 9380

def version = "0.4.1"
implementation "dev.chrisbanes.accompanist:accompanist-coil:$version"
implementation "dev.chrisbanes.accompanist:accompanist-insets:$version"
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        WindowCompat.setDecorFitsSystemWindows(window, false)
        setContent {
            // A surface container using the 'background' color from the theme
            val systemUiController = remember { SystemUiController(window) }
            Providers(SysUiController provides systemUiController) {
                ProvideWindowInsets {
                    val sysUiController = SysUiController.current

                    onCommit(sysUiController, LightColorPalette2.uiBackground) {
                        sysUiController.setSystemBarsColor(
                            color = LightColorPalette2.uiBackground.copy(alpha = AlphaNearOpaque)
                        )
                    }
                    Surface(color = MaterialTheme.colors.background) {
                        Greeting("Android")
                    }
                }
            }
        }
    }
}

and you also need this file:

package com.example.myjetsnack

import android.os.Build
import android.view.View
import android.view.Window
import androidx.compose.runtime.staticAmbientOf
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.graphics.luminance
import androidx.compose.ui.graphics.toArgb

interface SystemUiController {
    fun setStatusBarColor(
        color: Color,
        darkIcons: Boolean = color.luminance() > 0.5f,
        transformColorForLightContent: (Color) -> Color = BlackScrimmed
    )

    fun setNavigationBarColor(
        color: Color,
        darkIcons: Boolean = color.luminance() > 0.5f,
        transformColorForLightContent: (Color) -> Color = BlackScrimmed
    )

    fun setSystemBarsColor(
        color: Color,
        darkIcons: Boolean = color.luminance() > 0.5f,
        transformColorForLightContent: (Color) -> Color = BlackScrimmed
    )
}

fun SystemUiController(window: Window): SystemUiController {
    return SystemUiControllerImpl(window)
}

/**
 * A helper class for setting the navigation and status bar colors for a [Window], gracefully
 * degrading behavior based upon API level.
 */
private class SystemUiControllerImpl(private val window: Window) : SystemUiController {

    /**
     * Set the status bar color.
     *
     * @param color The **desired** [Color] to set. This may require modification if running on an
     * API level that only supports white status bar icons.
     * @param darkIcons Whether dark status bar icons would be preferable. Only available on
     * API 23+.
     * @param transformColorForLightContent A lambda which will be invoked to transform [color] if
     * dark icons were requested but are not available. Defaults to applying a black scrim.
     */
    override fun setStatusBarColor(
        color: Color,
        darkIcons: Boolean,
        transformColorForLightContent: (Color) -> Color
    ) {
        val statusBarColor = when {
            darkIcons && Build.VERSION.SDK_INT < 23 -> transformColorForLightContent(color)
            else -> color
        }
        window.statusBarColor = statusBarColor.toArgb()

        if (Build.VERSION.SDK_INT >= 23) {
            @Suppress("DEPRECATION")
            if (darkIcons) {
                window.decorView.systemUiVisibility = window.decorView.systemUiVisibility or
                    View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
            } else {
                window.decorView.systemUiVisibility = window.decorView.systemUiVisibility and
                    View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
            }
        }
    }

    /**
     * Set the navigation bar color.
     *
     * @param color The **desired** [Color] to set. This may require modification if running on an
     * API level that only supports white navigation bar icons. Additionally this will be ignored
     * and [Color.Transparent] will be used on API 29+ where gesture navigation is preferred or the
     * system UI automatically applies background protection in other navigation modes.
     * @param darkIcons Whether dark navigation bar icons would be preferable. Only available on
     * API 26+.
     * @param transformColorForLightContent A lambda which will be invoked to transform [color] if
     * dark icons were requested but are not available. Defaults to applying a black scrim.
     */
    override fun setNavigationBarColor(
        color: Color,
        darkIcons: Boolean,
        transformColorForLightContent: (Color) -> Color
    ) {
        val navBarColor = when {
            Build.VERSION.SDK_INT >= 29 -> Color.Transparent // For gesture nav
            darkIcons && Build.VERSION.SDK_INT < 26 -> transformColorForLightContent(color)
            else -> color
        }
        window.navigationBarColor = navBarColor.toArgb()

        if (Build.VERSION.SDK_INT >= 26) {
            @Suppress("DEPRECATION")
            if (darkIcons) {
                window.decorView.systemUiVisibility = window.decorView.systemUiVisibility or
                    View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
            } else {
                window.decorView.systemUiVisibility = window.decorView.systemUiVisibility and
                    View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv()
            }
        }
    }

    /**
     * Set the status and navigation bars to [color].
     *
     * @see setStatusBarColor
     * @see setNavigationBarColor
     */
    override fun setSystemBarsColor(
        color: Color,
        darkIcons: Boolean,
        transformColorForLightContent: (Color) -> Color
    ) {
        setStatusBarColor(color, darkIcons, transformColorForLightContent)
        setNavigationBarColor(color, darkIcons, transformColorForLightContent)
    }
}

/**
 * An [androidx.compose.runtime.Ambient] holding the current [SysUiController]. Defaults to a
 * no-op controller; consumers should [provide][androidx.compose.runtime.Providers] a real one.
 */
val SysUiController = staticAmbientOf<SystemUiController> {
    FakeSystemUiController
}

private val BlackScrim = Color(0f, 0f, 0f, 0.2f) // 20% opaque black
private val BlackScrimmed: (Color) -> Color = { original ->
    BlackScrim.compositeOver(original)
}

/**
 * A fake implementation, useful as a default or used in Previews.
 */
private object FakeSystemUiController : SystemUiController {
    override fun setStatusBarColor(
        color: Color,
        darkIcons: Boolean,
        transformColorForLightContent: (Color) -> Color
    ) = Unit

    override fun setNavigationBarColor(
        color: Color,
        darkIcons: Boolean,
        transformColorForLightContent: (Color) -> Color
    ) = Unit

    override fun setSystemBarsColor(
        color: Color,
        darkIcons: Boolean,
        transformColorForLightContent: (Color) -> Color
    ) = Unit
}

Upvotes: -3

Ahmed Maad
Ahmed Maad

Reputation: 551

I can answer the first part of your question:

How to make the status bar color transparent in Compose?

  1. According to Material Theming with Jetpack Compose Codelab and the official documentation, you can lay out your app in full screen behind the system bars (enable edge to edge) using setDecorFitsSystemWindows().
  2. Use Color.Transparent.toArgb() to set the status bar color to transparent.
  3. The system icon colors (e.g. battery level icon, Wi-Fi icon, ..., etc.) are set to either light or dark depending on whether the dark theme is enabled or not using isAppearanceLightStatusBars = !darkTheme (Notice the !).

Open Theme.kt inside your ui.theme package, and change the code inside SideEffect to the following:

SideEffect {
        val window = (view.context as Activity).window
        WindowCompat.setDecorFitsSystemWindows(window, false)
        window.statusBarColor = Color.Transparent.toArgb()
        WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme
    }

Upvotes: 1

Chandler
Chandler

Reputation: 3287

I think other answers are overthinking - unless you really want to change the status bar colour dynamically in the source code.

Just check out your src/main/res/values-night/themes.xml

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.HelloWorld" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        ...
        <item name="colorPrimaryVariant">@color/black</item>
        ...

        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
    </style>
</resources>

Upvotes: 25

Shahriar Zaman
Shahriar Zaman

Reputation: 938

Slight modification of @Patrik Lang, you can use this inside any @Composable functions:

@Composable
fun StatusBarColor(color: Color) {
    val view = LocalView.current
    val darkTheme = isSystemInDarkTheme()

    if (!view.isInEditMode) {
        SideEffect {
            val window = (view.context as Activity).window
            window.statusBarColor = color.toArgb()
            WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme
            WindowCompat.getInsetsController(window, view).isAppearanceLightNavigationBars = !darkTheme
        }
    }
}

Upvotes: 9

dolar
dolar

Reputation: 1785

Step 1 (add dependency) => version may change

implementation "com.google.accompanist:accompanist-systemuicontroller:0.27.0"

Step 2 => inside Theme.kt file

change the colors according to your need in the functions below.

val systemUiController = rememberSystemUiController()
if(darkTheme){
    systemUiController.setSystemBarsColor(
        color = Color.Transparent
    )
}else{
    systemUiController.setSystemBarsColor(
        color = Color.White
    )
}

Step 3 => ON systemUiController you can access all types of customizations you need for your app. Above is a sample for setSystemBarsColor

Upvotes: 119

Deepanshu Suman
Deepanshu Suman

Reputation: 77

Editing the Theme.kt file and making changes to these lines is a straightforward process.

if (!view.isInEditMode) {
        SideEffect {
            val window = (view.context as Activity).window
            window.statusBarColor = colorScheme.background.toArgb()
            window.navigationBarColor = colorScheme.background.toArgb()
            WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme
        }
    }

Upvotes: 4

antaki93
antaki93

Reputation: 860

Just use this code (e.g. in your ui.theme.Theme file):

SideEffect {
    val window = (view.context as Activity).window
    window.statusBarColor = YOUR_COLOR.toArgb()
}

It is template code from official Android Studio composable example.

Upvotes: 3

Allan Veloso
Allan Veloso

Reputation: 6369

  1. Make the screen edge to edge:

Follow this guide: https://developer.android.com/jetpack/compose/layouts/insets

  1. As an alternative to the deprecated Google accopanist library, you can use this composable extension (modified from the Google library):
@Composable
fun rememberWindowInsetController(
    window: Window? = findWindow(),
): WindowInsetsControllerCompat? {
    val view = LocalView.current
    return remember(view, window) {
        window?.let {
            WindowCompat.getInsetsController(it, view)
        }
    }
}

@Composable
private fun findWindow(): Window? =
    (LocalView.current.parent as? DialogWindowProvider)?.window
        ?: LocalView.current.context.findWindow()

private tailrec fun Context.findWindow(): Window? =
    when (this) {
        is Activity -> window
        is ContextWrapper -> baseContext.findWindow()
        else -> null
    }
  1. Then with a copy of WindowInsetsController, you can set the status bar color to light:
val windowInsetsController = rememberWindowInsetController()
windowInsetsController?.isAppearanceLightStatusBars = true
  1. Finally, the part of making the translucent bar is just place a translucent retangle of the size of the insets on the very top of your UI, behind the status bar icons:
    val systemBarHeight = WindowInsets.systemBars.getTop(LocalDensity.current).dp
    Spacer(
        modifier = Modifier
            .fillMaxWidth()
            .height(systemBarHeight)
            .background(Color.Gray.copy(alpha = 0.5f))
    )

Upvotes: 1

chethan
chethan

Reputation: 1

Change the color scheme in ui.theme folder > color.kt file, ex: val Purple80 = Color(0xFF495E57)

"primary" is responsible for status bar color which is in theme.kt file under ui.theme

Upvotes: 0

Jeevan Rupacha
Jeevan Rupacha

Reputation: 5806

use the new Activity.enableEdgeToEdge method available in androidx.activity 1.8.0-alpha03 and later

enableEdgeToEdge(
            statusBarStyle = SystemBarStyle.auto(TRANSPARENT, TRANSPARENT),
            navigationBarStyle = SystemBarStyle.auto(TRANSPARENT, TRANSPARENT)
        )

Upvotes: 2

Samuel Wakoli
Samuel Wakoli

Reputation: 300

This is how I approached this case:

I used the surface color for the status bar color, then added the not (!) at the darkTheme variable, so as to make the status bar icons visible in cases of light and dark theme.

val view = LocalView.current
    if (!view.isInEditMode) {
        SideEffect {
            val window = (view.context as Activity).window
            window?.statusBarColor =
                colorScheme.surface.toArgb() // surface becomes the the status bar color

            WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars =
                !darkTheme // not darkTheme makes the status bar icons visible
        }
    }

This is my general code

@Composable
fun MyAppNameTheme(
    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
            window?.statusBarColor =
                colorScheme.surface.toArgb() // surface becomes the the status bar color

            WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars =
                !darkTheme // not darkTheme makes the status bar icons visible
        }
    }

    MaterialTheme(
        colorScheme = colorScheme, typography = Typography, content = content
    )
}

Results:

My app in light theme image showing light theme status bar

My app in dark theme image showing dark theme status bar

Upvotes: 4

hcl2000
hcl2000

Reputation: 356

Updated answer Google's Accompanist library collection has has some changes and the systemuicontroller library is now deprecated.

The primary use case was to make it easier to go edge-to-edge. For this use case, there is now a direct replacement: Activity.enableEdgeToEdge

Keep the following in mind when using it:

The default style configures the system bars with a transparent background when contrast can be enforced by the system (API 29 or above).

To solve the problem post-deprecation, place this in your calling activity:

override fun onCreate(savedInstanceState: Bundle?) {
    enableEdgeToEdge()
    super.onCreate(savedInstanceState)
    // ...
}

Upvotes: 4

Thanh Nguyen
Thanh Nguyen

Reputation: 9

@Donny Rozendal gave best answer. Just to be clear :

implementation("com.google.accompanist:accompanist-systemuicontroller:0.30.1")

Theme.kt

@Composable
fun OneProjTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    // Dynamic color is available on Android 12+
    dynamicColor: Boolean = true,
    content: @Composable () -> Unit
) {
    val systemUiController = rememberSystemUiController()

    DisposableEffect(systemUiController, darkTheme){
        systemUiController.setSystemBarsColor( color = Color.Transparent, darkIcons = darkTheme)
        //systemUiController.setStatusBarColor(color = Color., darkIcons = darkTheme)
        systemUiController.setNavigationBarColor(color = Color.Transparent, darkIcons = darkTheme)

        onDispose {  }
    }

Activity.kt

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    WindowCompat.setDecorFitsSystemWindows(window, false)

Upvotes: 0

Mehedi Hasan
Mehedi Hasan

Reputation: 557

In Jetpack material3

Here's the theme.kt file that you need to modify.

[I comment that out where you need to make changes]

@Composable
fun WellnessTheme(
    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
          window.statusBarColor = colorScheme.background.toArgb() // here change the color
          window.navigationBarColor = colorScheme.background.toArgb() // here change the color

          // here change the status bar element color
          WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme
      }
    }

    MaterialTheme(
      colorScheme = colorScheme,
      typography = Typography,
      content = content
    )
}

Upvotes: 13

KTibow
KTibow

Reputation: 818

Open your Theme.kt and change the base code to this:

            val window = (view.context as Activity).window
            window.statusBarColor = colorScheme.background.toArgb()
            val wic = WindowCompat.getInsetsController(window, view)
            wic.isAppearanceLightStatusBars = !darkTheme

Upvotes: 2

takudzw_M
takudzw_M

Reputation: 356

This does the job

It works like a charm. Trust me

You can check the whole project here https://github.com/samuel23taku/WeatherApp


// Material 3
package com.example.weatherapp_jetpack_compose.ui.theme
import android.app.Activity
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat


    private val LightColors = lightColorScheme(
        primary = md_theme_light_primary,
        onPrimary = md_theme_light_onPrimary,
        primaryContainer = md_theme_light_primaryContainer,
        onPrimaryContainer = md_theme_light_onPrimaryContainer,
        secondary = md_theme_light_secondary,
        onSecondary = md_theme_light_onSecondary,
        secondaryContainer = md_theme_light_secondaryContainer,
        onSecondaryContainer = md_theme_light_onSecondaryContainer,
        tertiary = md_theme_light_tertiary,
        onTertiary = md_theme_light_onTertiary,
        tertiaryContainer = md_theme_light_tertiaryContainer,
        onTertiaryContainer = md_theme_light_onTertiaryContainer,
        error = md_theme_light_error,
        errorContainer = md_theme_light_errorContainer,
        onError = md_theme_light_onError,
        onErrorContainer = md_theme_light_onErrorContainer,
        background = md_theme_light_background,
        onBackground = md_theme_light_onBackground,
        surface = md_theme_light_surface,
        onSurface = md_theme_light_onSurface,
        surfaceVariant = md_theme_light_surfaceVariant,
        onSurfaceVariant = md_theme_light_onSurfaceVariant,
        outline = md_theme_light_outline,
        inverseOnSurface = md_theme_light_inverseOnSurface,
        inverseSurface = md_theme_light_inverseSurface,
        inversePrimary = md_theme_light_inversePrimary,
        surfaceTint = md_theme_light_surfaceTint,
        outlineVariant = md_theme_light_outlineVariant,
        scrim = md_theme_light_scrim,
    )


    private val DarkColors = darkColorScheme(
        primary = md_theme_dark_primary,
        onPrimary = md_theme_dark_onPrimary,
        primaryContainer = md_theme_dark_primaryContainer,
        onPrimaryContainer = md_theme_dark_onPrimaryContainer,
        secondary = md_theme_dark_secondary,
        onSecondary = md_theme_dark_onSecondary,
        secondaryContainer = md_theme_dark_secondaryContainer,
        onSecondaryContainer = md_theme_dark_onSecondaryContainer,
        tertiary = md_theme_dark_tertiary,
        onTertiary = md_theme_dark_onTertiary,
        tertiaryContainer = md_theme_dark_tertiaryContainer,
        onTertiaryContainer = md_theme_dark_onTertiaryContainer,
        error = md_theme_dark_error,
        errorContainer = md_theme_dark_errorContainer,
        onError = md_theme_dark_onError,
        onErrorContainer = md_theme_dark_onErrorContainer,
        background = md_theme_dark_background,
        onBackground = md_theme_dark_onBackground,
        surface = md_theme_dark_surface,
        onSurface = md_theme_dark_onSurface,
        surfaceVariant = md_theme_dark_surfaceVariant,
        onSurfaceVariant = md_theme_dark_onSurfaceVariant,
        outline = md_theme_dark_outline,
        inverseOnSurface = md_theme_dark_inverseOnSurface,
        inverseSurface = md_theme_dark_inverseSurface,
        inversePrimary = md_theme_dark_inversePrimary,
        surfaceTint = md_theme_dark_surfaceTint,
        outlineVariant = md_theme_dark_outlineVariant,
        scrim = md_theme_dark_scrim,
    )

    @Composable
    fun JetpackWeatherTheme(
        useDarkTheme: Boolean = isSystemInDarkTheme(),
        content: @Composable() () -> Unit
    ) {

        val colors = if (!useDarkTheme) {
            LightColors
        } else {
            DarkColors
        }
        val activity = LocalView.current.context as Activity
        val backgroundArgb = colors.background.toArgb()
        activity.window?.statusBarColor = backgroundArgb

        val wic = WindowCompat.getInsetsController(activity.window, activity.window.decorView)
        wic.isAppearanceLightStatusBars = !useDarkTheme
        MaterialTheme(
            colorScheme = colors,
            content = content
        )
    }

Upvotes: 0

Tushar Ahmed
Tushar Ahmed

Reputation: 151

In your Theme use this to change status bar color

val view = LocalView.current
if (!view.isInEditMode) {
    SideEffect {
        val window = (view.context as Activity).window
        window.statusBarColor = if (darkTheme)  Color.Black.toArgb() else Purple40.toArgb()

    }
}

Upvotes: 5

MohammadReza Eram
MohammadReza Eram

Reputation: 568

If you're not interested in using the accompanist library, you can write this code into your composable function:

val activity = LocalView.current.context as Activity
val backgroundArgb = MaterialTheme.colors.background.toArgb()
activity.window.statusBarColor = backgroundArgb

Also, for changing status bar icon color you can do like this:

val wic = WindowCompat.getInsetsController(window, window.decorView)
wic.isAppearanceLightStatusBars = false // Adapt it with your implementation

Upvotes: 12

Patrick Lang
Patrick Lang

Reputation: 751

Here's my solution without accompanist and pretty minimal. All is done in the Theme definition. This is the standard code that comes out if you create a new compose project, but with the block in the middle added:

@Composable
fun JtxBoardTheme(
    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 activity  = view.context as Activity
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                activity.window.navigationBarColor = colorScheme.primary.copy(alpha = 0.08f).compositeOver(colorScheme.surface.copy()).toArgb()
                activity.window.statusBarColor = colorScheme.background.toArgb()
                WindowCompat.getInsetsController(activity.window, view).isAppearanceLightStatusBars = !darkTheme
                WindowCompat.getInsetsController(activity.window, view).isAppearanceLightNavigationBars = !darkTheme
            }
        }
    }

    MaterialTheme(
        colorScheme = colorScheme,
        typography = Typography,
        content = content
    )
}

I am applying a color on the status and navigation bar. The color for the navigation bar is calculated as I would like to use the same color as the bottom app bar (which has an elevation of 2 which means a color overlay of the primary color of 8%).

            WindowCompat.getInsetsController(activity.window, view).isAppearanceLightStatusBars = !darkTheme
            WindowCompat.getInsetsController(activity.window, view).isAppearanceLightNavigationBars = !darkTheme

Those two lines takes care of the icons in the navigation and status bar. As WindowCompat.getInsetsController(activity.window, view).isAppearanceLightNavigationBars = !darkTheme is only available from Android API level 26 (O), I have limited the whole block to this version. If you only want a color for the status bar, then you could also go to min API level 23 (M).

I am not happy with the way how I calculate the color for the navigation bar, but it was the best way that worked also with dynamic colors.

Upvotes: 21

guerdaa
guerdaa

Reputation: 216

The answers are really complicated :o !!! You can change the style of the app from the style xml and that is it. Here an example from https://github.com/android/compose-samples/tree/main/Rally

<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Rally" parent="Theme.MaterialComponents.NoActionBar">
    <item name="android:statusBarColor">@color/statusBarColor</item>
    <item name="android:windowLightStatusBar" tools:targetApi="m">true</item>
    <item name="android:windowBackground">?attr/colorSurface</item>
</style>

The line responsible for changing the color of the status bar here is

<item name="android:statusBarColor">@color/statusBarColor</item>

But you have also to consider the text inside the status bar. If you set the color to black for example and you don't indicate that the chosen color is dark, the text inside will be black, and thus it will be invisible. To fix that you have to set the following attribute to false if the chosen color is dark otherwise true.

<item name="android:windowLightStatusBar" tools:targetApi="m">false</item>

Important Note: Don't forget to add the theme attribute to your manifest file:

    <application
    ...
    android:theme="@style/Theme.Rally">

Upvotes: 3

Donny Rozendal
Donny Rozendal

Reputation: 1054

Google has just created a library called accompanist.
You can find it here: https://github.com/google/accompanist

It contains multiple helpful libraries for Jetpack Compose, among which is a System UI Controller that you can use for changing the status bar color.

Docs - https://google.github.io/accompanist/systemuicontroller/

Upvotes: 65

oriohac
oriohac

Reputation: 337

The simple answer is: Head to your MainActivity.kt, then enter these codes

WindowCompat.setDecorFitsSystemWindows(window, false)

This comes before

    setContent{}

Then head to your values folder, open colors.xml and create

<color name="transparent">#00000000</color>

Go to themes open themes.xml and themes.xml(night) and place this code in the two files, in one of the style tags that has colors in it.

<item name="android:statusBarColor" tools:targetApi="l">@color/transparent</item>

That is the simple way to create a transparent status bar on Android.

Upvotes: 9

Code Poet
Code Poet

Reputation: 7975

I use this code, which I found in the Jetpack Compose samples. It works fine for me. Just tweak to your own liking.

@Composable
fun SystemUi(windows: Window) =
    MaterialTheme {
        windows.statusBarColor = MaterialTheme.colors.surface.toArgb()
        windows.navigationBarColor = MaterialTheme.colors.surface.toArgb()

        @Suppress("DEPRECATION")
        if (MaterialTheme.colors.surface.luminance() > 0.5f) {
            windows.decorView.systemUiVisibility = windows.decorView.systemUiVisibility or
                    View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
        }

        @Suppress("DEPRECATION")
        if (MaterialTheme.colors.surface.luminance() > 0.5f) {
            windows.decorView.systemUiVisibility = windows.decorView.systemUiVisibility or
                    View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
        }
    }

Upvotes: 15

2jan222
2jan222

Reputation: 1924

I use this: https://stackoverflow.com/a/22192691/9957384

It works but maybe there is a better solution in compose. For convenience, I suggest creating an Ambient

Upvotes: 1

Related Questions