hasan_shaikh
hasan_shaikh

Reputation: 1480

How to implement transparent status bar in Jetpack Compose Android

I want to implement transparent status bar in jetpack compose.

I have integrated the Accompanist library for this but it has no transparent effect on status bar.

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

// Remember a SystemUiController
val systemUiController = rememberSystemUiController()
val useDarkIcons = !isSystemInDarkTheme()

DisposableEffect(systemUiController, useDarkIcons) {
    // Update all of the system bar colors to be transparent, and use
    // dark icons if we're in light theme
    systemUiController.setStatusBarColor(
        color = Color.Transparent,
        darkIcons = useDarkIcons
    )

    // setStatusBarColor() and setNavigationBarColor() also exist

    onDispose {}
}

Tried this as well, but it has problem with the gesture navigation

val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
  val window = (view.context as Activity).window
  val insets = WindowCompat.getInsetsController(window, view)
  window.statusBarColor = Color.Transparent.toArgb() // choose a status bar color
  window.navigationBarColor = Color.Transparent.toArgb() // choose a navigation bar color
  insets.isAppearanceLightStatusBars = !useDarkTheme
  insets.isAppearanceLightNavigationBars = !useDarkTheme
 }
}

Kindly suggest a better solution for the transparent status bar.

enter image description here

Upvotes: 8

Views: 13155

Answers (6)

chankruze
chankruze

Reputation: 1146

Following @Abanoub Samir's answer (using enableEdgeToEdge() with local view removed) will draw the app content below the status bar as shown below.

enter image description here

To resolve this you can use Modifier.statusBarsPadding() in your @Composable component.

The solution

The recommended way to do this without enableEdgeToEdge is in Theme.kt inside SideEffect leveraging WindowInsetsControllerCompat. Default jetpack compose project template does have this SideEffect implemented. So, we can edit that section as shown below:

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

This will produce the output as shown below:

light mode dark mode

Hope this will be helpful 👍

Upvotes: 0

Abanoub Samir
Abanoub Samir

Reputation: 497

In Jetpack Compose you can make the status bar translucent using the new Edge-To-Edge API since accompanist-systemuicontroller is deprecated.

First, go to your Theme.kt and remove the view part from it (the following part):

// Remove this part
val view = LocalView.current
    if (!view.isInEditMode) {
        SideEffect {
            val window = (view.context as Activity).window
            window.statusBarColor = colorScheme.primary.toArgb()
            WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
        }
    }

Second, open your activity if it is MainActivity.kt or anything else and enable edge-to-edge on it, as following:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        enableEdgeToEdge() // Add this
        super.onCreate(savedInstanceState)
        // Your composables ...
    }
}

Now you can run and see the status bar became translucent.

But here is a tip, by default, calling enableEdgeToEdge() automatically adjusts the system bar style to be transparent and dynamically adapts the icon & text colors based on the device’s current theme (white for dark mode, black for light mode).

So you can control the icon & text colors like this:

    // For dark (black) colors
    enableEdgeToEdge(
        statusBarStyle = SystemBarStyle.dark(
            android.graphics.Color.TRANSPARENT,
        )
    )


    // For light (white) colors
    enableEdgeToEdge(
        statusBarStyle = SystemBarStyle.light(
            android.graphics.Color.TRANSPARENT,
            android.graphics.Color.TRANSPARENT
        )
    )

So handle the colors as you needed, leave it default to system or make it light or dark based on your use case.

Upvotes: 8

If you haven't gotten a solution to this you can use the accompanist library reference already answered below here

Upvotes: 0

Allan Veloso
Allan Veloso

Reputation: 6369

  1. Call WindowCompat.setDecorFitsSystemWindows(window, false) in Activity.onCreate. This call requests that your app display behind the system UI. Your app will then be in control of how those insets are used to adjust the UI.

  2. Set android:windowSoftInputMode="adjustResize" in your Activity's AndroidManifest.xml entry. This setting allows your app to receive the size of the software IME as insets, which you can use to pad and lay out content appropriately when the IME appears and disappears in your app.

  1. Adjust the color of the system bars and icons in your app's theme to be transparent:
<style name="Theme.MyApplication" parent="Theme.Material.DayNight.NoActionBar">
    <!--Other app theme properties-->
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:navigationBarColor">@android:color/transparent</item>
</style>

Source and more details: https://developer.android.com/jetpack/compose/layouts/insets

Upvotes: -1

Javlon
Javlon

Reputation: 1334

You have to enable full-screen mode to draw under statusbar:

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

And you can use WindowInsets to avoid drawing under "System gestures":

ViewCompat.setOnApplyWindowInsetsListener(view) { view, windowInsets ->
   val insets = windowInsets.getInsets(
       WindowInsetsCompat.Type.systemGestures()
   )
   view.updatePadding(
       insets.left, 
       insets.top, 
       insets.right, 
       insets.bottom
   )
   WindowInsetsCompat.CONSUMED
}

For more information, look at the documentation

Upvotes: 3

Mayur
Mayur

Reputation: 358

Try This

Add the below line to your Theme

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

after adding this line to the theme set this theme in your activity in which you want to set a transparent status bar

Your activity/container layout you wish to have a transparent status bar needs this property set:

android:fitsSystemWindows="true"

add in activity root layout

Upvotes: -1

Related Questions