Ivan Bychkov
Ivan Bychkov

Reputation: 308

Hide status bar in Android 10 (API 29) and use its space in the application

I am trying to hide status bar in Android 10. I've already read a lot of answers to similar questions, but they don't work for my device. The goal is to use the space of the status bar as a part of application view:

enter image description here

Some of the solutions described below work on emulator, but don't work on my physical device (Redmi Note 10, API version 29).

I would appreciate any advice.

What I have tried:
What I've managed to do.

I've managed to get two results, but neither of them is good for me.

  1. Translucent status bar.

enter image description here

  1. Completely black status bar without taking its space for app view.

enter image description here

UPDATE 10 May 2022:

According to the following answer it is impossible to use WindowInsetsController on API 29 or earlier: How do I hide the status bar in my Android 11 app?

SOLUTION 1

Proposed by @Zain.

Activity:

protected void onCreate(Bundle savedInstanceState) {
    ...
    WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
    WindowInsetsControllerCompat windowInsetsCompat = new WindowInsetsControllerCompat(getWindow(), getWindow().getDecorView());
    windowInsetsCompat.hide(WindowInsetsCompat.Type.statusBars());        
    windowInsetsCompat.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
    ...

theme.xml:

<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>

SOLUTION 2

Activity:

protected void onCreate(Bundle savedInstanceState) {
    ...        
    getWindow().getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LOW_PROFILE
    );        
    ...

theme.xml:

<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>

Upvotes: 7

Views: 9843

Answers (2)

Ivan Bychkov
Ivan Bychkov

Reputation: 308

I found the solution. The following line was necessary:

<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>

Upvotes: 1

Zain
Zain

Reputation: 40840

You need to display contents content edge-to-edge in your app (Documentation reference)

Step 1: Use: WindowCompat.setDecorFitsSystemWindows(window, false)

This is the primary step for ensuring that your app goes edge-to-edge, that is, laid out using the entire width and height of the display. Use WindowCompat.setDecorFitsSystemWindows(window, false) to lay out your app behind the system bars, as shown in the following code example:

Step 2: Hide the status bar using WindowInsetsControllerCompat:

    WindowInsetsControllerCompat(window, window.decorView).apply {
        // Hide the status bar
        hide(WindowInsetsCompat.Type.statusBars())
        // Allow showing the status bar with swiping from top to bottom
        systemBarsBehavior =
            WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
    }

Step 3: As from step 1 the activity contents at the bottom will be obscured by the bottom navigation bar; then you need to adjust the bottom margin of the root layout of the activity to height of the navigation bar by using WindowInsetsListener:

Kotlin:

// root layout of your activity
val root = findViewById<ConstraintLayout>(R.id.root)
ViewCompat.setOnApplyWindowInsetsListener(
    root
) { view: View, windowInsets: WindowInsetsCompat ->
    val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
    view.layoutParams = (view.layoutParams as FrameLayout.LayoutParams).apply {
        // draw on top of the bottom navigation bar
        bottomMargin = insets.bottom
    }

    // Return CONSUMED if you don't want the window insets to keep being
    // passed down to descendant views.
    WindowInsetsCompat.CONSUMED
}

Java:

WindowInsetsControllerCompat windowInsetsCompat = new WindowInsetsControllerCompat(getWindow(), getWindow().getDecorView());

windowInsetsCompat.hide(WindowInsetsCompat.Type.statusBars());
windowInsetsCompat.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);

// root layout of your activity
ConstraintLayout root = findViewById(R.id.root);

ViewCompat.setOnApplyWindowInsetsListener(
        root
        , (view, windowInsets) -> {
            Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
            FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
            params.bottomMargin = insets.bottom;
            return WindowInsetsCompat.CONSUMED;
        });

Step 4: Finally make sure that drawing in cutout area is allowed in your app's theme:

<item name="android:windowLayoutInDisplayCutoutMode">always</item>

Upvotes: 8

Related Questions