Showing content behind status and navigation bar
Asked Answered
I

3

7

This looks like a duplicate question but I am not able to do it. I want complete transparent(not translucent) status bar as well as navigation bar and want the content to appear behind them.

activity_details.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorPrimary"
    tools:context="com.bitspilanidvm.bosm2017.DetailsActivity">

<ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:src="@drawable/q"
    android:scaleType="centerCrop"/>

</LinearLayout>

v21 styles.xml

<resources>

<!-- Theme for API level > 21 -->
<style name="AppTheme" parent="AppBaseTheme">
     <!--Customize your theme here. -->
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:navigationBarColor">@android:color/transparent</item>
</style>

In the activity java file

getWindow().getDecorView().setSystemUiVisibility(
        View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
               View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        );

This is what I get.

enter image description here

How to get content behind the navigation bar?

If I add

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

to my styles.xml

Here is what I get

enter image description here

As you can see, the content goes behind navigation bar but the navigation bar has to be translucent for this.

Is there any solution for this?

Ine answered 5/8, 2017 at 23:26 Comment(1)
nice does this device have no hard back button ?Desjardins
N
20

Add the FLAG_LAYOUT_NO_LIMITS flag within the Window. This will work for Android KitKat and above APIs. Example of this would be something like this:

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        Window window = getWindow(); 
     window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
    }

The reason why the FLAG_FULLSCREEN doesn't work is simply because the FULLSCREEN flag is for removing screen decors like status bar(which works for you). However Navigation bar is not a screen decor. The LAYOUT_NO_LIMIT flag allows the window to extend beyond the screen limit, hence Navigation bar also gets covered within this flag.

Also you could simply hide the navigation and status bar by setting the app in immersive mode.

EDIT The API ViewCompat.setOnApplyWindowInsetListener solves issues which the android:fitsSystemWindows=”true” does not and window insets can be applied to a particular view. An example of this.

ViewCompat.setOnApplyWindowInsetsListener(toolbar, (v, insets) -> {
    ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
    params.topMargin = insets.getSystemWindowInsetTop();
    return insets.consumeSystemWindowInsets();
});

Standard layouts like FrameLayout , LinearLayout or RelativeLayout will not pass window insets to their children, whereas material layouts will do (e.g. DrawerLayout , CoordinatorLayout ). So we can change our layout to any material one, or we can subclass a standard layout and pass the insets to the children of layout ourselves. We just have to override onApplyWindowInsets method.

@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
    int childCount = getChildCount();
    for (int index = 0; index < childCount; ++index)
        getChildAt(index).dispatchApplyWindowInsets(insets); 
        // let children know about WindowInsets

    return insets;
}

Reference Documentation:OnApplyWindowInsetsListener, WindowInsets

Nahshon answered 6/8, 2017 at 8:42 Comment(4)
Thanks! It worked perfectly. Can you please explain in brief why so? Why setting the decor view system ui visibility flags to View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN didn't worked?Ine
The reason why the FLAG_FULLSCREEN doesn't work is simply because the FULLSCREEN flag is for removing screen decors like status bar(which works for you). However Navigation bar is not a screen decor. The LAYOUT_NO_LIMIT flag allows the window to extend beyond the screen limit, hence Navigation bar also gets covered within this flag.Nahshon
This works! But the issue now is that the window never applies insets, so I have no way of knowing where the status bar and navigation bar are (without using some hacky work around). Any clues as to how we can still receive insets in onApplyWindowInsets()?Curitiba
@Curitiba I don't understand your question. The status and navigation bar are transparent after applying the above code. You could apply the insets to any particular view. Layouts like FrameLayout , LinearLayout etc. don't not pass window insets to their children, whereas material layouts (DrawerLayout, CoordinatorLayout ) will do. I have editted the answer and added about insets. But I am still vague about your question.Nahshon
P
9

I wanted to comment the accepted answer but i can't yet.

Just to warn everyone who'll take this approach

The FLAG_LAYOUT_NO_LIMITS let extend your root view outside of the screen bounds creating other concerns about your layout design. For example, this flag simply breaks form readability by forcing the system to ignore "adjustPan" and "adjustResize" flags

So, even though i still consider Ahbi's answer as the correct one, make sure that nothing breaks outside of the scope of this flag

BETTER SOLUTION:

Actually, i've just found a better way to achieve the same result, without breaking anything

This is my style file

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:navigationBarColor">@android:color/transparent</item>

</style>

And these are the flags that i set programmatically

w.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
w.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);

Setting the flag LAYOUT_HIDE_NAVIGATION (in combination with the style items) did the trick and my form still reacts to the adjustPan flag

Psychosocial answered 23/5, 2018 at 10:6 Comment(1)
While answering the question, I had not considered other flags like adjustPan. Thanks for the correction.Nahshon
H
0

If you want the image showing behind the status bar

getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

but by doing this, fitsSystemWindows="true" is not working toolbar overlaps to status bar.

Hernardo answered 28/10, 2020 at 12:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.