Android Material: Status bar color won't change

AndroidStatusbarMaterial Design

Android Problem Overview


I'm developing an simple app to test the material design. I'm using com.android.support:appcompat-v7:21.0.0 and my activity looks like:

public class MyActivity extends ActionBarActivity {
   ...
}

The layout is defined as:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MyActivity">

    <android.support.v7.widget.Toolbar
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="128dp"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimaryDark"/>
</LinearLayout>

Now i defined my theme following material guidelines:

<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="colorPrimary">@color/colorPrimary500</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark700</item>
</style>

I'd like to change the status bar color in pre Android 5 and set it to colorPrimaryDark but i can't find the way. I tried using:

getWindow().setStatusBarColor(..)

but setStatusBar color is available from level 21. Why if i define a colorPrimaryDark in my theme and use appcompact the status bar doesn't change color? Anyone can help?

Android Solutions


Solution 1 - Android

The status bar is a system window owned by the operating system. On pre-5.0 Android devices, applications do not have permission to alter its color, so this is not something that the AppCompat library can support for older platform versions. The best AppCompat can do is provide support for coloring the ActionBar and other common UI widgets within the application.

Solution 2 - Android

While colouring the status bar is not supported <5.0, on 4.4 you can use a work around to achieve a darker colour:

Make the status bar translucent

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

Then use AppCompat's Toolbar for your appbar, making sure that it fits system windows:

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    ...
    android:fitsSystemWindows="true"/>

Make sure to set your toolbar as your activity's toolbar:

protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ...
    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

The toolbar stretches underneath the status bar, and the semi translucency of the status bar makes it appear to be a darker secondary colour. If that's not the colour you want, this combination allows you to fit a view underneath your status bar sporting the background colour of your choice (though it's still tinted darker by the status bar).

Kind of an edge case workaround due to 4.4 only, but there ya go.

Solution 3 - Android

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    getWindow().setStatusBarColor(getResources().getColor(R.color.actionbar));
}

Put this code in your Activity's onCreate method. This helped me.

Solution 4 - Android

As others have also mentioned, this can be readily solved by adding the following to the onCreate() of the Activity:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        getWindow().setStatusBarColor(ContextCompat.getColor(this, R.color.primary_dark));
    }

However, the important point I want to add here is that in some cases, even the above does not change the status bar color. For example, when using MikePenz library for Navigation Drawer, it implicityly overrides the status bar color, so that you need to manually add the following for it to work:

.withStatusBarColorRes(R.color.status_bar_color)

Solution 5 - Android

Status bar coloring is not supported in AppCompat v7:21.0.0.

From the Android developers blog post

> On older platforms, AppCompat emulates the color theming where possible. At the moment this is limited to coloring the action bar and some widgets.

This means the AppCompat lib will only color status bars on Lollipop and above.

Solution 6 - Android

Switch to AppCompatActivity and add a 25 dp paddingTop on the toolbar and turn on

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

Then, the will toolbar go up top the top

Solution 7 - Android

This solution sets the statusbar color of Lollipop, Kitkat and some pre Lollipop devices (Samsung and Sony). The SystemBarTintManager is managing the Kitkat devices ;)

@Override
protected void onCreate( Bundle savedInstanceState ) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	hackStatusBarColor(this, R.color.primary_dark);
}

@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public static View hackStatusBarColor( final Activity act, final int colorResID ) {
	if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
		try {

			if (act.getWindow() != null) {

				final ViewGroup vg = (ViewGroup) act.getWindow().getDecorView();
				if (vg.getParent() == null && applyColoredStatusBar(act, colorResID)) {
					final View statusBar = new View(act);

					vg.post(new Runnable() {
						@Override
						public void run() {

							int statusBarHeight = (int) Math.ceil(25 * vg.getContext().getResources().getDisplayMetrics().density);
							statusBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, statusBarHeight));
							statusBar.setBackgroundColor(act.getResources().getColor(colorResID));
							statusBar.setId(13371337);
							vg.addView(statusBar, 0);
						}
					});
					return statusBar;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	else if (act.getWindow() != null) {
		act.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
		act.getWindow().setStatusBarColor(act.getResources().getColor(colorResID));
	}
	return null;
}

private static boolean applyColoredStatusBar( Activity act, int colorResID ) {
	final Window window = act.getWindow();
	final int flag;
	if (window != null) {
		View decor = window.getDecorView();
		if (decor != null) {
			flag = resolveTransparentStatusBarFlag(act);

			if (flag != 0) {
				decor.setSystemUiVisibility(flag);
				return true;
			}
			else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
				act.findViewById(android.R.id.content).setFitsSystemWindows(false);
				setTranslucentStatus(window, true);
				final SystemBarTintManager tintManager = new SystemBarTintManager(act);
				tintManager.setStatusBarTintEnabled(true);
				tintManager.setStatusBarTintColor(colorResID);
			}
		}
	}
	return false;
}

public static int resolveTransparentStatusBarFlag( Context ctx ) {
	String[] libs = ctx.getPackageManager().getSystemSharedLibraryNames();
	String reflect = null;

	if (libs == null)
		return 0;

	final String SAMSUNG = "touchwiz";
	final String SONY = "com.sonyericsson.navigationbar";

	for (String lib : libs) {

		if (lib.equals(SAMSUNG)) {
			reflect = "SYSTEM_UI_FLAG_TRANSPARENT_BACKGROUND";
		}
		else if (lib.startsWith(SONY)) {
			reflect = "SYSTEM_UI_FLAG_TRANSPARENT";
		}
	}

	if (reflect == null)
		return 0;

	try {
		Field field = View.class.getField(reflect);
		if (field.getType() == Integer.TYPE) {
			return field.getInt(null);
		}
	} catch (Exception e) {
	}

	return 0;
}

@TargetApi(Build.VERSION_CODES.KITKAT)
public static void setTranslucentStatus( Window win, boolean on ) {
	WindowManager.LayoutParams winParams = win.getAttributes();
	final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
	if (on) {
		winParams.flags |= bits;
	}
	else {
		winParams.flags &= ~bits;
	}
	win.setAttributes(winParams);
}

Solution 8 - Android

Make Theme.AppCompat style parent

<style name="AppTheme" parent="Theme.AppCompat">
     <item name="android:colorPrimary">#005555</item>
     <item name="android:colorPrimaryDark">#003333</item>
</style>

And put getSupportActionBar().getThemedContext() in onCreate().

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);
        getSupportActionBar().getThemedContext();
}

Solution 9 - Android

I know this doesn't answer the question, but with Material Design (API 21+) we can change the color of the status bar by adding this line in the theme declaration in styles.xml:

<!-- MAIN THEME -->
<style name="AppTheme" parent="@android:style/Theme.Material.Light">
    <item name="android:actionBarStyle">@style/actionBarCustomization</item>
    <item name="android:spinnerDropDownItemStyle">@style/mySpinnerDropDownItemStyle</item>
    <item name="android:spinnerItemStyle">@style/mySpinnerItemStyle</item>
    <item name="android:colorButtonNormal">@color/myDarkBlue</item>
    <item name="android:statusBarColor">@color/black</item>
</style>

Notice the android:statusBarColor, where we can define the color, otherwise the default is used.

Solution 10 - Android

**

Solution for naughty LOLLIPOP

**

hello i had rly big problem with having that darker than was my color... so this is solution to avoid that shadow behind status bar from solution with TranslucentStatus...

so in all of your java activity you need this:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    }

and at your styles.xml you need to set background color (this color will be your status bar color):

<style name="AppCompat" parent="Theme.AppCompat">
    <item name="android:colorBackground">@color/YOUR_STATUS_BAR_COLOR</item>
</style>

and at all your layouts you need to add layout which will be your background:

<LinearLayout
    android:background="@color/YOUR_BACKGROUND_COLOR"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="bottom"
    />

of course if you would like use @color/just name... you need to set that at colors.xml:

<color name="YOUR_STATUS_BAR_COLOR">#cf031c</color>
<color name="YOUR_BACKGROUND_COLOR">#383838</color>

here is whole process how we did done that: https://stackoverflow.com/questions/60188515/whats-the-right-approach-to-create-or-change-color-of-a-status-bar/60197129#60197129

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFrancescoAzzolaView Question on Stackoverflow
Solution 1 - AndroidAlex LockwoodView Answer on Stackoverflow
Solution 2 - AndroidTomView Answer on Stackoverflow
Solution 3 - Androiduser998953View Answer on Stackoverflow
Solution 4 - AndroidMehrAmoonView Answer on Stackoverflow
Solution 5 - AndroidAnup CowkurView Answer on Stackoverflow
Solution 6 - AndroidalvarlagerlofView Answer on Stackoverflow
Solution 7 - AndroidbaphoView Answer on Stackoverflow
Solution 8 - AndroidAusamaView Answer on Stackoverflow
Solution 9 - AndroidApostrofixView Answer on Stackoverflow
Solution 10 - Androidkobra zlobraView Answer on Stackoverflow