How to Customize Status Bar in Jetpack Compose?

Jetpack Compose Customize Status Bar

In this article, we’ll learn how to customize the system bars (status bar and navigation bar) in Jetpack Compose using the System Ui Controller library.

First, What are System Bars in Android?

By default, apps are displayed below the status bar and above the navigation bar.

The status bar displays notification and system icons at the top of the screen.

Android Status Bar

The navigation bar contains controls like back and home at the bottom of the screen.

Navigation Bar

Together, the status bar and the navigation bar are called the system bars.

Jetpack Compose System Ui Controller:

The System Ui Library is used for customizing the status bar and navigation bars.

First, add the following dependency in the app level build.gradle file:

// system bars customization
implementation "com.google.accompanist:accompanist-systemuicontroller:0.30.1"

Make sure that the version you are using is compatible with Jetpack Compose version.

Now, we can play with the system bars. First, we need the SystemUiController object. We can get it from the rememberSystemUiController() composable.

val systemUiController = rememberSystemUiController()

Now we can call methods to modify the system bars.

Status Bar Color:

The setStatusBarColor() method changes the status bar color.

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

color – The color to be applied on the status bar.

darkIcons – Whether the icons on the status bar should be dark icons. It is also applicable to text on the status bar.

transformColorForLightContent – It is a lambda that will be invoked to transform color if dark icons were requested but are not available.

Call the method inside the SideEffect composable. We should set the system bar colors inside the Theme block (in the onCreate() method).

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import com.google.accompanist.systemuicontroller.rememberSystemUiController

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            YourProjectNameTheme {

                val systemUiController = rememberSystemUiController()
                SideEffect {
                    systemUiController.setStatusBarColor(
                        color = Color.Magenta,
                        darkIcons = false
                    )
                }

                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                }
            }
        }
    }
}

Output:

Status Bar Color

Instead of adding the code in every activity, you can paste it into the Theme.kt file. In the project pane, open ui > theme > Theme.kt and add the code inside your Theme block.

Theme Jetpack Compose

In the place of BlogPostsTheme, you will see your project name (YourProjectNameTheme).

Related: Understanding Themes in Jetpack Compose

Navigation Bar Color:

Use the setNavigationBarColor() method to change the navigation bar color.

val systemUiController = rememberSystemUiController()
SideEffect {
    systemUiController.setNavigationBarColor(
        color = Color.Magenta,
        darkIcons = false
    )
}

Output:

Navigation Bar color

We can change the color of both using the setSystemBarsColor() method.

val systemUiController = rememberSystemUiController()
SideEffect {
    systemUiController.setSystemBarsColor(
        color = Color.Magenta,
        darkIcons = false
    )
}

Note: Android supports dark icons for the status bar on API 23+ and navigation bar color on API 26+. The library automatically handles the API differences and maintains the icon and text contrast.

How to Hide Status Bar in Jetpack Compose?

System Ui Controller provides getter and setter properties to hide or show system bars.

isNavigationBarVisible and isStatusBarVisible are for setting the visibility for the navigation bar and status bar respectively. isSystemBarsVisible is for both the system bars.

val systemUiController = rememberSystemUiController()
SideEffect {
    // navigation bar
    systemUiController.isNavigationBarVisible = false

    // status bar
    systemUiController.isStatusBarVisible = false

    // system bars
    // systemUiController.isSystemBarsVisible = false
}

How to Make Status Bar Transparent?

If we make the status bar transparent, we can display the app content behind it. For example, let’s make this design:

Content Behind the Status Bar

First, download the image from Unsplash and change its name to squirrel.jpg. Put it in the res > drawable folder.

We need to extend the app window to the system bars. We can do that with the help of setDecorFitsSystemWindows() method. Call it before the super.onCreate() method.

WindowCompat.setDecorFitsSystemWindows(window, false)

To make the image visible, set transparent color to the status bar.

val systemUiController = rememberSystemUiController()
SideEffect {
   systemUiController.setStatusBarColor(color = Color.Transparent)
}

Display the image using Image composable.

Image(
    painter = painterResource(id = R.drawable.squirrel),
    contentDescription = "Squirrel",
    contentScale = ContentScale.FillWidth,
    modifier = Modifier.fillMaxWidth()
)

Here is full the code:

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.core.view.WindowCompat
import com.google.accompanist.systemuicontroller.rememberSystemUiController

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {

        // expanded the app UI to system bars
        WindowCompat.setDecorFitsSystemWindows(window, false)

        super.onCreate(savedInstanceState)

        // instead of WindowCompat.setDecorFitsSystemWindows(),
        // you can also use the following
        // window.setFlags(
        // WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
        // WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
        // )

        setContent {
            YourProjectNameTheme {

                val systemUiController = rememberSystemUiController()
                SideEffect {
                    // set transparent color so that our image is visible
                    // behind the status bar
                    systemUiController.setStatusBarColor(color = Color.Transparent)
                }

                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    Column(modifier = Modifier.fillMaxSize()) {
                        Image(
                            painter = painterResource(id = R.drawable.squirrel),
                            contentDescription = "Squirrel",
                            contentScale = ContentScale.FillWidth,
                            modifier = Modifier.fillMaxWidth()
                        )
                    }
                }
            }
        }
    }
}

In the above code, our app will be extended to the navigation bar also. There are 3 ways to fix this:

  1. If you are using Jetpack Compose 1.2.0, use the navigationBarsPadding() method.
  2. If you are using the previous version, follow this guide.
  3. Set the FLAG_LAYOUT_NO_LIMITS only on the status bar.

Version 1.2.0 introduced the navigationBarsPadding() method. We can use it to get the navigation bar height and apply it as padding.

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.core.view.WindowCompat
import com.google.accompanist.systemuicontroller.rememberSystemUiController

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {

        // expanded the app UI to system bars
        WindowCompat.setDecorFitsSystemWindows(window, false)

        super.onCreate(savedInstanceState)

        setContent {
            YourProjectNameTheme {

                val systemUiController = rememberSystemUiController()

                SideEffect {
                    // set the transparent color so that our image is visible
                    // behind the status bar
                    systemUiController.setStatusBarColor(color = Color.Transparent)

                    // I tried to make the navigation bar transparent
                    // but, it's not working
                    // systemUiController.setNavigationBarColor(color = Color.Transparent)
                }

                Surface(
                    modifier = Modifier
                        .fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {

                    LazyColumn(
                        modifier = Modifier
                            .fillMaxSize()
                        .navigationBarsPadding() // adds padding below
                    ) {
                        // display 4 images
                        items(count = 4) {
                            Image(
                                painter = painterResource(id = R.drawable.squirrel),
                                contentDescription = "Squirrel",
                                contentScale = ContentScale.FillWidth,
                                modifier = Modifier.fillMaxWidth()
                            )
                        }
                    }
                }
            }
        }
    }
}

Output:

If the video isn’t working, watch it on the YouTube.

Related: LazyColumn API (with Examples)

Similarly, we can use statusBarsPadding() to get the status bar height and set it as padding.

You can find the GitHub repo of the library here. This is all about customizing the status bar in Jetpack Compose. If you have any doubts, comment below.

Continue Exploring Jetpack Compose:

References:

Leave a Comment