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:

错误的布局

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

正确的布局

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>

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.


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.


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.

链接地址: http://www.djcxy.com/p/92468.html

上一篇: WebRTC:RTCDataChannel不是“打开”

下一篇: Android:透明状态栏,带有动态的动作条颜色和DrawerLayout