Search code examples
androidxmlandroid-coordinatorlayoutdrawerlayoutandroid-statusbar

Android: Transparent status bar with dynamic actionBar colors and DrawerLayout


I have an activity with a DrawerLayout. Our client requires us to dynamically change the action bar color and the corresponding status bar color of this activity depending upon the item selected from the DrawerLayout. This is easily done. However, my problem is that I am not being able to keep the status bar transparent when I dynamically change the status bar color. When I open the drawer, the colored status bar covers the top of the DrawerLayout like this:

wrong layout

However, I would like my DrawerLayout to look like this:

correct layout

This I can do with the following line:

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

However, my problem is not that I can't set the transparency of the status bar. My problem is that the dynamic changing of the status bar and action bar color doesn't work with windowTranslucentStatus. My status bar color remains the colorPrimaryDark (the mustard-yellowish color visible on the status bar in the pictures above) even after I call getWindow().setStatusBarColor().

Now, I followed this tutorial and this and this stackoverflow questions among many others, but was unable to resolve the issue. All of these articles say that the ActionBar will move to the top, underneath the status bar (so that the status bar overlaps the action bar) once I set the windowTranslucentStatus to true. Afterwards, I should be able to add some padding to the action bar and simply changing the action bar color would also result in a darker status bar of the same color since the status bar is actually translucent and overlapping my action bar. However, for some reason, this does not happen in my case. The action bar stays where it is whether I set fitsSystemWindows to true or false or remove the attribute altogether. The action bar is always below the status bar which is, of course, always yellow if I set transparency.

I have also tried setting an alpha to the status bar color when changing it programmatically. This does make the status bar somewhat transparent, but it looks odd since it is not really dark anymore. Removing the CoordinatorLayout is of no help, either. I have spent several hours trying to fix this and am quite frustrated now. Any help is greatly appreciated.

My activity_main:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">

<include
    layout="@layout/app_bar_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

<android.support.design.widget.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true">

    <include layout="@layout/nav_header_main" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/nav_menu_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="@dimen/nav_header_height"
        android:clipToPadding="false"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/size_14dp"
        app:layoutManager="LinearLayoutManager" />
</android.support.design.widget.NavigationView>

</android.support.v4.widget.DrawerLayout>

And here is the XML for my app_bar_main:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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:fitsSystemWindows="true">

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay"
    app:elevation="0dp">


    <FrameLayout
        android:id="@+id/toolbar_container"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:popupTheme="@style/AppTheme.PopupOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary" />

        <com.quintype.sakshipost.Widgets.CustomMaterialSearchView
            android:id="@+id/search_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </FrameLayout>

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

<include layout="@layout/content_main" />

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

Solution

  • Your problem is caused because getWindow().setStatusBarColor() does not work well with the DrawerLayout. In order to keep your status bar translucent as well as being able to change its color, you have to follow the process below:

    Add/modify the following theme in your v21/styles.xml file as below:

    <style name="AppTheme.NoActionBar" parent="AppTheme">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:windowTranslucentStatus">true</item>
    </style>
    

    This is the theme that the standard DrawerLayout uses (assuming, of course, that you are using this theme in the activity that has the DrawerLayout). This will make your status bar translucent, as you already know.

    Next, remove android:fitsSystemWindows="true" from the CoordinatorLayout in your app_bar_main.

    Next, wherever you are changing the color of the toolbar/status bar, use drawerLayout.setStatusBarBackground(colorDrawable) using the same color you use for the toolbar (assuming, of course, that the reference to your DrawerLayout is called drawerLayout). Note that the drawerLayout.setStatusBarBackground() method takes a Drawable object, unlike the window.setStatusBarColor() method, which takes an int color, so you may have to convert your color to a drawable using something like this:

    new ColorDrawable(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary))
    

    This will make sure that your status bar is translucent as well as give it the ability to change colors. Hope you are able to get this to work.