Using windowTranslucentStatus with CollapsingToolbarLayout

39,272

Solution 1

Add fitsSystemWindows to layout and set to true.

Update

Sorry for my incomplete answer. You should add fitsSystemWindows="true" to layout xml like below codes.

<android.support.design.widget.CoordinatorLayout
    android:id="@+id/main"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:background="@color/background_material_dark"
        android:fitsSystemWindows="true">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsingToolbarLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:minHeight="?attr/actionBarSize"
            app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
            app:statusBarScrim="#09b"
            app:contentScrim="#09f"
            android:fitsSystemWindows="true">

            <ImageView
                android:id="@+id/img"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:src="@drawable/location_banner"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.7"
                android:fitsSystemWindows="true"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_height="?attr/actionBarSize"
                android:layout_width="match_parent"
                app:layout_collapseMode="pin"
                android:fitsSystemWindows="true"
                app:theme="@style/ThemeOverlay.AppCompat.ActionBar"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Dark"/>

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

</android.support.design.widget.CoordinatorLayout>

Solution 2

There has now been an update to the design library. I'm guessing that the issue posted above was a bug.

If you update the design library to the latest version this issue no longer occurs.

I have now removed all fitsSystemWindows="true" except for the ImageView (as that needs to display under the status bar).

I have also removed the minus padding from the Toolbar.

This is my theme for 21+

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowActionBarOverlay">true</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:textColorPrimary">@android:color/white</item>
</style>

It all works as expected now

Solution 3

The best way to achieve this is like Stimsoni said

Add android:fitsSystemWindows="true" to the CoordiatorLayout, AppBarLayout and ImageView

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">

<android.support.design.widget.AppBarLayout
    android:id="@+id/appBar"
    android:fitsSystemWindows="true"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:contentScrim="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

        <ImageView
            android:id="@+id/background"
            android:layout_width="match_parent"
            android:layout_height="256dp"
            android:scaleType="centerCrop"
            android:fitsSystemWindows="true"
            app:layout_collapseMode="parallax"
            android:alpha="0.75"
            android:src="@drawable/foo"/>

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_collapseMode="pin"/>
    </android.support.design.widget.CollapsingToolbarLayout>        
</android.support.design.widget.AppBarLayout>...

Solution 4

Extend the CoordinatorLayout and call setOnApplyWindowInsetsListener in your constructor to reset inset values. Here is the code:

public class CustomCoordinatorLayout extends CoordinatorLayout {
    public CustomCoordinatorLayout(Context context) {
        super(context);
        init();
    }

    public CustomCoordinatorLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CustomCoordinatorLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
            setOnApplyWindowInsetsListener(new OnApplyWindowInsetsListener() {
                @Override
                public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
                    WindowInsets replaced = windowInsets.replaceSystemWindowInsets(0, 0, 0, 0);
                    return replaced;
                }
            });
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

Solution 5

Once the status bar is transparent and the free to use by the activity, the toolbar is pushed top to occupy that space. To fix this you need to manually move the toolbar to the original spot.

Add the below tags to the "android.support.v7.Widget.Toolbar" view :

android:layout_height="48dp" // Whatever the height of the toolbar you want
android:layout_marginTop="-48dp" // Negative of the height of the toolbar
Share:
39,272
Stimsoni
Author by

Stimsoni

Updated on June 01, 2020

Comments

  • Stimsoni
    Stimsoni almost 4 years

    I'm trying to get a similar effect to what is seen on google play.

    I've got the below layout to show a transparent toolbar with an image behind it. When the user scrolls there is a parallax effect on the imageview as it scrolls off the screen. The toolbar returns when ever the user scrolls up, with the imageview only returning when the user gets to the lop of the list.

    This all works great.

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/main"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    
        <android.support.design.widget.AppBarLayout
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:background="@color/background_material_dark">
            <android.support.design.widget.CollapsingToolbarLayout
                android:id="@+id/collapsingToolbarLayout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:minHeight="?attr/actionBarSize"
                app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
                app:statusBarScrim="#09b"
                app:contentScrim="#09f">
                <ImageView
                    android:id="@+id/img"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:src="@drawable/location_banner"
                    app:layout_collapseMode="parallax"
                    app:layout_collapseParallaxMultiplier="0.7"
                    />
                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_height="?attr/actionBarSize"
                    android:layout_width="match_parent"
                    app:layout_collapseMode="pin"
                    android:fitsSystemWindows="true"
                    app:theme="@style/ThemeOverlay.AppCompat.ActionBar"
                    app:popupTheme="@style/ThemeOverlay.AppCompat.Dark"/>
            </android.support.design.widget.CollapsingToolbarLayout>
        </android.support.design.widget.AppBarLayout>
    
    </android.support.design.widget.CoordinatorLayout>
    

    The issue

    When I set windowTranslucentStatus to true. The contents in the view move up to be under the status bar, but the contents of the CollapsingToolbarLayout moves up twice the height of the status bar(CollapsingToolbarLayout retains correct height).

    This means some of the top of the image is cut off and the actionbar now appears under the status bar instead of below it. As a side effect of this there is now padding at the bottom of the CollapsingToolbarLayout the same height as the status bar

    This is what it looks like without windowTranslucentStatus. Everything here works fine enter image description here

    windowTranslucentStatus set to true enter image description here

    User scrolling up from lower in list (not at top) enter image description here

  • Stimsoni
    Stimsoni almost 9 years
    Are you saying for the toolbar height you aren't using "?attr/actionBarSize". you have that height + 16dp. Having this padding without the height would mean the bottom of the contents in toolbar would be pushed off the bottom of the view.
  • tvgemert
    tvgemert almost 9 years
    It could be helpful to post a code example like: fitsSystemWindows = true or something like that
  • Stimsoni
    Stimsoni almost 9 years
    Where abouts do i add it. I did some testing with this and it didn't quite work. As you can see it has been added to toolbar in the xml posted. I found that this did add some padding, but it only pushed the toolbar down half the amount expected. It also didn't fix the image being cut off
  • Stimsoni
    Stimsoni almost 9 years
    Sorry for the delay in response. This got me most of the way there thank you, but still didn't move the toolbar down. I had to combine your answer with Henry's to get me over the line. For anyone else reading I added "fitsSystemWindows" to the CoordiatorLayout, AppBarLayout and ImageView. I then had to add android:layout_marginTop="-48dp"(standard toolbar height) to the Toolbar view as mentioned by Henry's answer.
  • Stimsoni
    Stimsoni almost 9 years
    Thanks Henry, I had to combine your answer with David's to get this to work properly.
  • Brandon Slaght
    Brandon Slaght about 8 years
    Sorry to bump this @Stimsoni, but is this fully working?? For me, this works with the imageview going behind the statusbar, but when I scroll the content down to show the toolbar, nothing is drawn behind the statusbar.
  • Stimsoni
    Stimsoni about 8 years
    That sounds right. When the toolbar comes back into view so does the status bar. If you want the content to be behind the toolbar but reappear above it you can try adding a transparent scrim on the status bar. I haven't tested this as yet though
  • Vincent D.
    Vincent D. about 8 years
    Thanks, at the end we need a 16dp paddingTop, removing the fitsSystemWindow=true from the layout and activating <item name="android:windowTranslucentStatus">true</item> to work.
  • Simon
    Simon over 7 years
    replaceSystemWindowInsets requires api> 20
  • Etienne Lawlor
    Etienne Lawlor almost 6 years
    I didnt know app:statusBarScrim was a property until i saw this answer. It helped me fix another bug i found : reddit.com/r/androiddev/comments/8xai0g/…
  • mparkes
    mparkes over 5 years
    This was causing a bug in the newer library ('com.android.support:design:27.1.1') version where my view pager had too much padding on top. I've removed the android:fitsSystemWindows="true" from the coordinator layout and the behavior is as expected.
  • Stimsoni
    Stimsoni over 5 years
    I love comments like this. Doesn't work????? Sooooo..... what doesn't work? any errors? what's happening?