8

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>
Community
  • 1
  • 1

3 Answers3

8

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.

Ishita Sinha
  • 2,168
  • 4
  • 25
  • 38
0

As doc says here, FLAG_TRANSLUCENT_STATUS must not be set.

For this to take effect, the window must be drawing the system bar backgrounds with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS and FLAG_TRANSLUCENT_STATUS must not be set.

GPack
  • 2,494
  • 4
  • 19
  • 50
  • I had tried this as well, but this results in the same behavior as in the first screen shot. I want it to look like the second, but still be able to change the status bar color. I could also simply make the status bar transparent and extend the action bar underneath it. But I'm unable to do either. :( –  Jul 07 '16 at 07:54
-2

I do this in my app like this.

<style name="AppTheme" parent="Theme.AppCompat.Dark">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>

the colorPrimary will set the status bar color, but only if you restart the activity.

so set that to a transparent black color, then in your code restart the activity. You can make more than one style in styles, with different colorPrimary values, then in your activity do this.

//onClick or condition statement here
setTheme(R.style.AppThemeLight);
setContentView(R.layout.activity_link_manager_light);
restart();


public void restart(){
Intent i = getBaseContext().getPackageManager()
            .getLaunchIntentForPackage( getBaseContext().getPackageName() );
    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(i);
}

I don't think you need to reset the contentview unless you are switching layouts as well, not sure you can try resetting it to the same layout if it's not working without it.

This definitely works for me but i've never tried to use a transparent value.

You can use this method to reset the entire app theme and switch to a new layout that has different colors hardcoded into it, just leave all the id's the same on the layout and in code you will get the right id as long as you reference the findViewByID AFTER you have setContentView to the proper layout that has the ID you call in it somewhere. The id's for each layout are different but you will always get the ID of the layout that is currently set with setContentView at the time you call findViewByID.

you can also save your current theme to a sharedpref file and use a switch to set the theme upon applaunch before setContentView is called (otherwise the statusbar color won't change)

consider this code. This is near the start of onCreate by the way

String Theme;
    SaveData = getSharedPreferences(SaveFileName,0);
    Theme = SaveData.getString("Theme","Default Theme");
switch(Theme){
        case "Light Theme":
            setTheme(R.style.AppThemeLight);
            setContentView(R.layout.activity_link_manager_light);
            ListTextViewID = R.id.AppListTextViewLight;
            ListRowID = R.layout.app_list_item_light;
            break;

The way i set the apptheme before i set the contentview is why the statusbar color change works.

Jon halls
  • 44
  • 6
  • You may not have understood my question fully. I can easily set the color of the status bar using `getWindow().setStatusBarColor(int color);` You neither need to restart the activity for that nor call `setContentView()` multiple times. However, my goal is to set the status bar to _transparent_ and draw the action bar _underneath_ it. (Additionally, restarting an activity multiple times for such a trivial matter is a very inelegant hack.) –  Jul 05 '16 at 10:36
  • O yeah i missed that, well you can do that too by switching the theme parent from ".NoActionBar" to ".Light" which will add an action bar and you can set the color using the theme as well. this will do everything you want but i don't know how to do it without restarting the application. – Jon halls Jul 05 '16 at 10:39
  • you could also add a custom action bar programatically by having a linearlayout or view where the action bar would be, and hide and display it programatically by: "View.setVisibility(View.GONE);" "View.setVisibility(View.VISIBLE);" – Jon halls Jul 05 '16 at 10:43
  • Actually to correct myself i don't think it restarts the app, just the activity, it has a painless animation and it's fast (atleast on MM it is) – Jon halls Jul 05 '16 at 10:45
  • Trust me. Restarting an activity multiple times is not something you should do. You don't need to change the theme either. You seem fairly new to Android. Have you ever worked with a `DrawerLayout`? –  Jul 05 '16 at 10:48
  • You are changing the colors alot? I assumed this wasn't multiple times... – Jon halls Jul 05 '16 at 10:51
  • there is nothing wrong with that practice to set the theme of an app, it will only restart when the user changes a theme, every other time it will load the theme they left off with last time, the first time and not have to restart. hence the savedprefs. – Jon halls Jul 05 '16 at 10:52