155

I have set my statusBar color to transparent for Lollipop only with the following line in my theme :

<item name="android:statusBarColor">@android:color/transparent</item>

Now I need to draw behind it, but I can't get any view draw behind it. I know how to do it with the windowTranslucentStatus property, but don't want to use this property since it will then ignore the color of the statusBar set to transparent.

alxscms
  • 3,067
  • 6
  • 22
  • 43

16 Answers16

401

Method #1:

To achieve a completely transparent status bar, you have to use statusBarColor, which is only available on API 21 and above. windowTranslucentStatus is available on API 19 and above, but it adds a tinted background for the status bar. However, setting windowTranslucentStatus does achieve one thing that changing statusBarColor to transparent does not: it sets the SYSTEM_UI_FLAG_LAYOUT_STABLE and SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN flags. The easiest way to get the same effect is to manually set these flags, which effectively disables the insets imposed by the Android layout system and leaves you to fend for yourself.

You call this line in your onCreate method:

getWindow().getDecorView().setSystemUiVisibility(
    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

Be sure to also set the transparency in /res/values-v21/styles.xml:

<item name="android:statusBarColor">@android:color/transparent</item>

Or set the transparency programmatically:

getWindow().setStatusBarColor(Color.TRANSPARENT);

The good side to this approach is that the same layouts and designs can also be used on API 19 by trading out the transparent status bar for the tinted translucent status bar.

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

Method #2:

If you only need to paint a background image under your status bar, instead of positioning a view behind it, this can be done by simply setting the background of your activity's theme to the desired image and setting the status bar transparency as shown in method #1. This was the method I used to create the screenshots for the Android Police article from a few months ago.

Method #3:

If you've got to ignore the standard system insets for some layouts while keeping them working in others, the only viable way to do it is to work with the often linked ScrimInsetsFrameLayout class. Of course, some of the things done in that class aren't necessary for all scenarios. For example, if you don't plan to use the synthetic status bar overlay, simply comment out everything in the init() method and don't bother adding anything to the attrs.xml file. I've seen this approach work, but I think you'll find that it brings some other implications that may be a lot of work to get around.

I also saw that you're opposed to wrapping multiple layouts. In the case of wrapping one layout inside of another, where both have match_parent for height and width, the performance implications are too trivial to worry about. Regardless, you can avoid that situation entirely by changing the class it extends from FrameLayout to any other type of Layout class you like. It will work just fine.

Community
  • 1
  • 1
Cody Toombs
  • 4,380
  • 2
  • 15
  • 18
  • 9
    Thanks a lot, setting the `SYSTEM_UI_FLAG_LAYOUT_STABLE` and `SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN` flags was the solution I was looking for. – alxscms Jan 20 '15 at 09:27
  • 1
    Hi. Your code works perfectly fine. But when I exit the fragment, How should I rollback changes? – TheOnlyAnil Oct 02 '15 at 18:18
  • 3
    This doesn't work with `CollapsingToolbarLayout` and `Toolbar`: status bar stay not fully translucent and `android:statusBarColor` takes no effect – Konstantin Konopko Mar 29 '16 at 16:00
  • Thanks. If you then want to revert back to a non-fullscreen activity, read http://developer.sonymobile.com/knowledge-base/tutorials/android_tutorial/how-to-provide-your-app-users-with-maximum-screen-estate-tutorial/. – CoolMind Sep 16 '16 at 10:58
  • method 2# can any one tell me how I can set image(each time different) in theme programmatically – Sanjeev Dec 15 '16 at 20:03
  • Note that if you are targeting older device, you probably need to have another xml layout with different dimensions, since old device black status bar will cover you content if you do not use another layout. – Sira Lam Sep 21 '17 at 04:55
  • Method 1: It has nothing to do with `android:fitsSystemWindows="true"` or `CoordinateLayout` or themes, it just works – Bugs Happen Feb 16 '18 at 05:10
  • I really like the look of the tinted statusbar I get with windowTranslucentStatus, is there a way to get this on > API 19? The completely transparent statusbar doesn't look as good to me. – Felix Eder Apr 10 '18 at 08:07
  • Cody Toombs , could I use one of this methods to achiev this ? -> https://stackoverflow.com/questions/48817316/status-bar-sensitive-information-like-telegram-x – Arthur Melo Jun 26 '18 at 03:45
  • I am using Method 1 in a Fragment and its working fine. How do i reset it in `onDetach()`? – Diaz diaz Jul 04 '18 at 11:57
  • In my case, I have to remove android:fitsSystemWindows="true". Works on Android 8.1. – Kharda Dec 05 '18 at 09:58
  • Beware that SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN will not add padding when the keypad is shown! – Kamen Dobrev Jun 17 '19 at 14:24
48

This worked for my case


// Create/Set toolbar as actionbar
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

// Check if the version of Android is Lollipop or higher
if (Build.VERSION.SDK_INT >= 21) {

    // Set the status bar to dark-semi-transparentish
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
            WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

    // Set paddingTop of toolbar to height of status bar.
    // Fixes statusbar covers toolbar issue
    toolbar.setPadding(0, getStatusBarHeight(), 0, 0);
}

// A method to find height of the status bar
public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

For more information about working with statusBars: youtube.com/watch?v=_mGDMVRO3iE


Michael
  • 9,639
  • 3
  • 64
  • 69
  • @TheOnlyAnil define a fixed toolbar height :) "56dp" or so should look good – Michael Oct 21 '15 at 14:17
  • 4
    Getting the status bar height like this is totally unsupported, undocumented, and will surely break in future versions. Use fitsSystemWindows="true" instead. – Greg Ennis Mar 01 '16 at 13:35
  • @GregEnnis probably true :/ – Michael Mar 01 '16 at 21:29
  • 1
    Well I'm doing it also cause sometimes you just have to . – Greg Ennis Mar 02 '16 at 00:39
  • 2
    This is a very bad idea, according to Chris Banes (Google Engineer) in this talk: https://www.youtube.com/watch?v=_mGDMVRO3iE – Martin Marconcini Jun 19 '18 at 22:47
  • @MartinMarconcini I agree! Use this at your own risk. It could (and I have seen it) create extra bars above your view. – Michael Jun 20 '18 at 13:37
  • 1
    @Michael FWIW, I’ve done this in the past and the WindowInsets api an (method) to do this “should be simple and done without us having to think about it”, but it’s not, it’s a lame useless API that adds a lot of unneeded overhead. Google is always 80% complete and leave the last 20% to the devs… who hack all the way until they make it happen. ¯\_(ツ)_/¯ – Martin Marconcini Jun 21 '18 at 19:07
22

Try this theme

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    <item name="colorPrimaryDark">@android:color/transparent</item>
    <item name="colorPrimary">@color/md_blue_200</item>
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:windowTranslucentStatus">true</item>
</style>

Be sure that, your layout set

android:fitsSystemWindows="false"
Son Nguyen Thanh
  • 1,199
  • 15
  • 19
17

Instead of

<item name="android:statusBarColor">@android:color/transparent</item>

Use the following:

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

And make sure to remove the top padding (which is added by default) on your 'MainActivity' layout.

Note that this does not make the status bar fully transparent, and there will still be a "faded black" overlay over your status bar.

Jeroen Mols
  • 3,436
  • 17
  • 24
  • 2
    When using `true`, it makes android put a faded black background under the status bar which is not what I am looking for. Any way though to not have this black faded background? – alxscms Jan 14 '15 at 09:54
  • 1
    I've tried many things, but I cannot find a way to remove the faded black background. Therefore I am concluding my research by saying it is not possible on Android (even not with the ScrimLayout). This kind of makes sense, because it ensures proper readability of your status bar at all times. I'll update my answer above. – Jeroen Mols Jan 15 '15 at 07:06
  • I think it would be very weird to be able to put a transparent color to the status bar, without being able to draw behind it. I understand why you say it makes sense that you can't remove this black faded background, but it is definitely not that hard to be careful enough to keep the status bar icon visible. Here is an article of android police showing the use of a transparent status bar http://www.androidpolice.com/2014/07/04/android-l-spotlight-colored-transparent-status-bars-give-apps-even-control-design/. I will try to contact the author. – alxscms Jan 16 '15 at 14:34
  • 1
    Hope you can get in touch with him. I'm getting very interested in doing this as well :) – Jeroen Mols Jan 17 '15 at 13:41
  • Great! Updated my answer as well. – Jeroen Mols Jan 20 '15 at 09:32
10

The solution from Cody Toombs almost did the trick for me. I'm not sure if this is Xamarin related or not, but I now have an acceptable solution:

Example

This is my setup:

I have an Android project where I have referenced the Android.Support v4 and v7 packages. I have two styles defined:

values/styles.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<resources>
    <style name="MyStyle" parent="@style/Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowTranslucentStatus">true</item>
    </style>
</resources>

values-v21/styles.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<resources>
    <style name="MyStyle" parent="@style/Theme.AppCompat.Light.NoActionBar">
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
</resources>

AndroidManifest targets "MyStyle":

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.agn.test.test">
    <uses-sdk android:minSdkVersion="10" />
    <application android:allowBackup="true" android:icon="@mipmap/icon" android:label="@string/app_name" android:theme="@style/MyStyle">
    </application>
</manifest>

And finally the code in the Main Activity:

[Activity (Label = "Test", MainLauncher = true, Icon = "@mipmap/icon")]
public class MainActivity : Activity
{
    protected override void OnCreate (Bundle savedInstanceState)
    {
        base.OnCreate (savedInstanceState);

        SetContentView (Resource.Layout.Main);
        //Resource.Layout.Main is just a regular layout, no additional flags. Make sure there is something in there like an imageView, so that you can see the overlay.

        var uiOptions = (int)Window.DecorView.SystemUiVisibility;
        uiOptions ^= (int)SystemUiFlags.LayoutStable;
        uiOptions ^= (int)SystemUiFlags.LayoutFullscreen;
        Window.DecorView.SystemUiVisibility = (StatusBarVisibility)uiOptions;

        Window.AddFlags (WindowManagerFlags.DrawsSystemBarBackgrounds);
    }
}

Notice that I set DrawsSystemBarBackgrounds flag, this makes all the difference

Window.AddFlags (WindowManagerFlags.DrawsSystemBarBackgrounds); 

I spent a lot of time getting it right, too much time in fact. Hopefully this answer helps anyone trying to achieve the same thing.

Gerhard Schreurs
  • 663
  • 1
  • 8
  • 19
  • 1
    ```android:windowTranslucentStatus``` requires API level 19 or above, how's it possible that you are using it on your **values/styles.xml** while having a ```android:minSdkVersion``` of 10? – mradzinski Jan 27 '17 at 01:07
9

@Cody Toombs's answer lead to an issue that brings the layout behind the navigation bar. So what I found is using this solution given by @Kriti

here is the Kotlin code snippet for the same:

if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
    setWindowFlag(this, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, true)
}

if (Build.VERSION.SDK_INT >= 19) {
    window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
}

if (Build.VERSION.SDK_INT >= 21) {
    setWindowFlag(this, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, false)
    getWindow().setStatusBarColor(Color.TRANSPARENT)
}

private fun setWindowFlag(activity: Activity, bits: Int, on: Boolean) {

    val win: Window = activity.getWindow()

    val winParams: WindowManager.LayoutParams = win.getAttributes()
    if (on) {
        winParams.flags = winParams.flags or bits
    } else {
        winParams.flags = winParams.flags and bits.inv()
    }
    win.setAttributes(winParams)
}

You also need to add

android:fitsSystemWindows="false"

root view of your layout.

Kishan Solanki
  • 13,761
  • 4
  • 85
  • 82
2

I had the same problem so i create ImageView that draw behind status bar API 19+

Set custom image behind Status Bar gist.github.com

public static void setTransparent(Activity activity, int imageRes) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
        return;
    }
    // set flags
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
    } else {
        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    }

    // get root content of system window
    //ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
    // rootView.setFitsSystemWindows(true);
    // rootView.setClipToPadding(true);

    ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
    if (contentView.getChildCount() > 1) {
        contentView.removeViewAt(1);
    }

    // get status bar height
    int res = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
    int height = 0;
    if (res != 0)
        height = activity.getResources().getDimensionPixelSize(res);

    // create new imageview and set resource id
    ImageView image = new ImageView(activity);
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height);
    image.setLayoutParams(params);
    image.setImageResource(imageRes);
    image.setScaleType(ScaleType.MATRIX);

    // add image view to content view
    contentView.addView(image);
    // rootView.setFitsSystemWindows(true);

}
Sumit
  • 1,022
  • 13
  • 19
1

You can use ScrimInsetFrameLayout

https://github.com/google/iosched/blob/master/android/src/main/java/com/google/samples/apps/iosched/ui/widget/ScrimInsetsFrameLayout.java

android:fitsSystemWindows="true" should set on scrim layout!

Murtaza Khursheed Hussain
  • 15,176
  • 7
  • 58
  • 83
1

I will be adding some more information here. The latest Android developments have made it pretty easy to handle a lot of cases in status bar. Following are my observations from the styles.xml

  1. Background color: for SDK 21+, as a lot of answers mentioned,<item name="android:windowTranslucentStatus">true</item> will make the status bar transparent and show in front of UI. Your Activity will take the whole space of the top.
  2. Background color: again,for SDK 21+, <item name="android:statusBarColor">@color/your_color</item> will simply give a color to your status bar, without affecting anything else.

  3. However, in later devices (Android M/+), the icons started coming in different shades. The OS can give a darker shade of gray to the icons for SDK 23/+ , if you override your styles.xml file in values-23 folder and add <item name="android:windowLightStatusBar">true</item>.
    This way, you will be providing your user with a more visible status bar, if your status bar has a light color( think of how a lot of google apps have light background yet the icons are visible there in a greyish color).
    I would suggest you to use this, if you are giving color to your status bar via point #2

  4. In the most recent devices, SDK 29/+ comes with a system wide light and dark theme, controllable by the user. As devs, we are also supposed to override our style file in a new values-night folder, to give user 2 different experiences.
    Here again, I have found the point #2 to be effective in providing the "background color to status bar". But system was not changing the color of status bar icons for my app. since my day version of style consisted of lighter theme, this means that users will suffer from low visibility ( white icons on lighter background)
    This problem can be solved by using the point #3 approach or by overriding style file in values-29 folder and using a newer api <item name="android:enforceStatusBarContrast">true</item> . This will automatically enforce the grayish tint to icons, if your background color is too light.

ansh sachdeva
  • 1,220
  • 1
  • 15
  • 32
0

With Android Studio 1.4, the template project with boiler plate code sets Overlay theme on your AppbarLayout and/or Toolbar. They are also set to be rendered behind the status bar by fitSystemWindow attribute = true. This will cause only toolbar to be rendered directly below the status bar and everything else will rendered beneath the toolbar. So the solutions provided above won't work on their own. You will have to make the following changes.

  • Remove the Overlay theme or change it to non overlay theme for the toolbar.
  • Put the following code in your styles-21.xml file.

    @android:color/transparent

  • Assign this theme to the activity containing the navigation drawer in the AndroidManifest.xml file.

This will make the Navigation drawer to render behind the transparent status bar.

Umer Farooq
  • 7,356
  • 7
  • 42
  • 67
0

Similar to some of the solutions posted, but in my case I did the status bar transparent and fix the position of the action bar with some negative margin

if (Build.VERSION.SDK_INT >= 21) {
    getWindow().setStatusBarColor(Color.TRANSPARENT);
    FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) toolbar.getLayoutParams();
    lp.setMargins(0, -getStatusBarHeight(), 0, 0);
}

And I used in the toolbar and the root view

android:fitsSystemWindows="true"
jegumi
  • 1,162
  • 10
  • 17
  • 1
    getStatusBarHeight() is not standard – Roel May 25 '16 at 11:25
  • This method is implemented on the solution from @mike-milla... public int getStatusBarHeight() { int result = 0; int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = getResources().getDimensionPixelSize(resourceId); } return result; } – jegumi May 26 '16 at 13:03
  • Thanks. I made so: AppBarLayout.LayoutParams lp = (AppBarLayout.LayoutParams) toolbar.getLayoutParams(); lp.topMargin += getStatusBarHeight(); – CoolMind Sep 24 '16 at 20:33
0

There is good library StatusBarUtil from @laobie that help to easily draw image in the StatusBar.

Just add in your build.gradle:

compile 'com.jaeger.statusbarutil:library:1.4.0'

Then in the Activity set

StatusBarUtil.setTranslucentForImageView(Activity activity, int statusBarAlpha, View viewNeedOffset)

In the layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:background="@color/white"
    android:orientation="vertical">

    <ImageView
        android:layout_alignParentTop="true"
        android:layout_width="match_parent"
        android:adjustViewBounds="true"
        android:layout_height="wrap_content"
        android:src="@drawable/toolbar_bg"/>

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/view_need_offset"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@android:color/transparent"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

        <!-- Your layout code -->
    </android.support.design.widget.CoordinatorLayout>
</RelativeLayout>

For more info download demo or clone from github page and play with all feature.

Note: Support KitKat and above.

Hope that helps somebody else!

Gueorgui Obregon
  • 5,077
  • 3
  • 33
  • 57
0

All you need to do is set these properties in your theme

<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
Sudhir Singh
  • 817
  • 11
  • 16
  • 1
    I'm pretty sure this will make your layout fall underneath the UI navigation buttons (devices with on-screen navigation). This made bottom navigation view inaccessible in our app, so we ditched these flags after testing on a Nexus – EpicPandaForce Dec 08 '18 at 13:36
0

The accepted answer worked for me using a CollapsingToolbarLayout. It's important to note though, that setSytstemUiVisibility() overrides any previous calls to that function. So if you're using that function somewhere else for the same view, you need to include the View.SYSTEM_UI_FLAG_LAYOUT_STABLE and View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN flags, or they will be overridden with the new call.

This was the case for me, and once I added the two flags to the other place I was making a call to setSystemUiVisibility(), the accepted answer worked perfectly.

Cameron
  • 1,281
  • 1
  • 19
  • 40
-1

Here is the theme I use to accomplish this:

<style name="AppTheme" parent="@android:style/Theme.NoTitleBar">

    <!-- Default Background Screen -->
    <item name="android:background">@color/default_blue</item>
    <item name="android:windowTranslucentStatus">true</item>

</style>
Droid Chris
  • 3,455
  • 28
  • 31
-3

The Right solution is to Change a property in XML under your Activity tag to below style. It just works

  android:theme="@style/Theme.AppCompat.Light.NoActionBar"
satya phani
  • 45
  • 1
  • 6