renzhn
renzhn

Reputation: 691

completely transparent status bar and navigation bar on lollipop

I'm trying to make an android launcher. I want to achieve a completely transparent status bar and navigation bar, here is my theme xml file.

<resources>
    <style name="Theme" parent="android:Theme.Material.Wallpaper.NoTitleBar">
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:navigationBarColor">@android:color/transparent</item>
        <item name="android:windowTranslucentStatus">false</item>
        <item name="android:windowTranslucentNavigation">false</item>
    </style>
</resources>

the last two items don't work, there is still a shadow on lollipop.

This is what it looks like(note there is actually a shadow on status bar and navigation bar): enter image description here

what I want to achieve (nova launcher):

enter image description here

how to make the status bar and navigation bar "transparent" instead of "translucent"?

Upvotes: 69

Views: 139306

Answers (14)

Amr
Amr

Reputation: 1312

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

This will get you a transparent system bars until api 29.

From api 29+ you need to add

    <item name="android:enforceNavigationBarContrast">false</item>

this will stop the system from enforcing scrim color to ensure contrast -> on the left enforceNavigationBarContrast=true, on the right equal to false.

enforceNavigationBarContrast=true enforceNavigationBarContrast=false

using only xml you will have to create two theme files like this ->

right click on themes folder -> new -> values resource files step1 step2 result

in order to make all of this to work these attributes must be false as stated here, also if you just remove them from xml AND you are not setting the equivalent flags in code then they are turned off by default.

    <item name="android:windowTranslucentNavigation">false</item>
    <item name="android:windowTranslucentStatus">false</item>

also make sure that your view is full screen by setting

    WindowCompat.setDecorFitsSystemWindows(window, false)

in onCreate

Extra
sometimes you will need to change nav/status bar icons in case they blends with the background, in this case you have two options, light/dark icons, to change them you need to add

    <item name="android:windowLightNavigationBar">true</item>
    <item name="android:windowLightStatusBar">true</item>

to do same changes i mentioned above but using code you will need these extensions functions

  1. To change light status/nav bar

     fun Window.setLightStatusBar(state: Boolean) {
         if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
             insetsController?.setSystemBarsAppearance(
                 /* appearance = */ if (state) 0 else APPEARANCE_LIGHT_STATUS_BARS,
                 /* mask = */ APPEARANCE_LIGHT_STATUS_BARS
             )
         } else {
             decorView.systemUiVisibility = if (state) 0 else SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
         }
     }
    
     fun Window.setLightNavigationBar(state: Boolean) {
         if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
             insetsController?.setSystemBarsAppearance(
                 /* appearance = */ if (state) 0 else APPEARANCE_LIGHT_NAVIGATION_BARS,
                 /* mask = */ APPEARANCE_LIGHT_NAVIGATION_BARS
             )
         } else {
             decorView.systemUiVisibility = if (state) 0 else SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
         }
     }
    
  2. To set nav bar contrast

     fun Window.setNavigationBarContrastEnforcedIfSupported(enabled: Boolean) {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
             isNavigationBarContrastEnforced = enabled
         }
     }
    
  3. to change colors to transparent

      window.setNavigationBarContrastEnforcedIfSupported(false)
      window.statusBarColor = Color.TRANSPARENT
      window.navigationBarColor = Color.TRANSPARENT
    

pay special attention that

  1. calling setNavigationBarContrastEnforcedIfSupported must happen before setting nav bar color to transparent otherwise it will not take effect

  2. if you are changing system bar light mode by code then you must remove any

     <item name="android:windowLightStatusBar">true</item>
     <item name="android:windowLightNavigationBar">true</item>
    

from xml otherwise it will not work, somehow when you use the deprecated decorView.systemUiVisibility -which is used by the xml attributes i guess- then when you try to mix its use with insetsController?.setSystemBarsAppearance they both stop to working properly, check this answer for more info

also here is a good article about system bars colors

Upvotes: 1

Ebrahim Byagowi
Ebrahim Byagowi

Reputation: 11228

Update: Just use androidx.activity.enableEdgeToEdge() instead

Outdated:

Based on Arpan Sarkar answer just made use of WindowCompat to reduce amount of code and avoid uses of deprecated definitions,

fun Activity.transparentSystemBars(
    behindStatusBarIsLight: Boolean,
    behindNavigationBarIsLight: Boolean,
) {
    // Android 4 is hard to debug and apparently ViewCompat.setOnApplyWindowInsetsListener isn't
    // reporting any value there so let's skip and simplify
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return

    WindowCompat.setDecorFitsSystemWindows(window, false)

    if (behindStatusBarIsLight || behindNavigationBarIsLight) {
        val insetsController: WindowInsetsControllerCompat =
            WindowCompat.getInsetsController(window, window.decorView)
        if (behindStatusBarIsLight)
            insetsController.isAppearanceLightStatusBars = true
        if (behindNavigationBarIsLight)
            insetsController.isAppearanceLightNavigationBars = true
    }
    
    val isLightStatusBarAvailable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
    val isLightNavigationBarAvailable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
    val shouldStatusBarBeTransparent = !behindStatusBarIsLight || isLightStatusBarAvailable
    val shouldNavigationBarBeTransparent = !behindNavigationBarIsLight || isLightNavigationBarAvailable

    val systemUiScrim = ColorUtils.setAlphaComponent(Color.BLACK, 0x40) // 25% black
    window.statusBarColor = if (shouldStatusBarBeTransparent) Color.TRANSPARENT else systemUiScrim
    window.navigationBarColor = if (shouldNavigationBarBeTransparent) Color.TRANSPARENT else systemUiScrim

    // You may set android:enforceNavigationBarContrast to false in style.xml as doing it in code isn't as effective apparently.
}

There is also EdgeToEdgeUtils.applyEdgeToEdge in the Material library which works but isn't supposed to be used by regular developers, guess it will be provided to the public someday.

Upvotes: 0

Shubham Gupta
Shubham Gupta

Reputation: 1353

From Android R

fun Activity.setTransparentStatusBar() {
    WindowCompat.setDecorFitsSystemWindows(window, false)
    window.statusBarColor = Color.TRANSPARENT
    window.navigationBarColor = Color.TRANSPARENT
}

That's it

Upvotes: 0

New-Way
New-Way

Reputation: 647

This is for the new guys like myself on Nativescript + Angular. I started off with one of the blank templates on the NTS marketplace. Then For my specific use, I need the status bar on top to be always transparent (similar to the iOS style) and the navbar (bottom) to be fully transparent (not translucent!) on some components/modules, while opaque in others. If everything is done according to the protocol set by NTS, you should have a main.ts (a prerequisite for my solution) similar to this enter image description here

I separated my work into two pieces, top first, then the bottom. For the top I found this answer that worked. So you should have a main.ts file that looks like this.

import { platformNativeScriptDynamic } from "@nativescript/angular";

import { AppModule } from "./app/app.module";

import * as application from "tns-core-modules/application";
import { Color } from "@nativescript/core";

platformNativeScriptDynamic().bootstrapModule(AppModule);

declare var android;

application.android.on(application.AndroidApplication.activityCreatedEvent, (event) => {

    const activity = event.activity;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
    activity.getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    activity.getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    activity.getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    activity.getWindow().setStatusBarColor(android.graphics.Color.TRANSPARENT);
    activity.getWindow().setNavigationBarColor(android.graphics.Color.TRANSPARENT);

} else {
    activity.getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    activity.getWindow().setNavigationBarColor(android.graphics.Color.TRANSPARENT);
}

const parent = activity.findViewById(android.R.id.content);
for (let i = 0; i < parent.getChildCount(); i++) {
    const childView = parent.getChildAt(i);
    if (childView instanceof android.view.ViewGroup) {
        childView.setFitsSystemWindows(true);
        childView.setClipToPadding(true);
    }
}

});

Then to add transparency to the navbar, I followed this and I add this to line 24 of the main.ts file above. activity.getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

Now mind you there are also the styles.xml files we have to respect, so my styles.xml file (App_Resources\Android\src\main\res\values\styles.xml) looks like this:

    <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">

<!-- theme to use FOR launch screen-->
<style name="LaunchScreenThemeBase" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="toolbarStyle">@style/NativeScriptToolbarStyle</item>
    <item name="colorPrimary">@color/ns_primary</item>
    <item name="colorPrimaryDark">@color/ns_primaryDark</item>
    <item name="colorAccent">@color/ns_accent</item>
    <item name="android:windowBackground">@drawable/splash_screen</item>
    <item name="android:statusBarColor">@color/transparent</item>
</style>

<style name="LaunchScreenTheme" parent="LaunchScreenThemeBase"></style>

<!-- theme to use AFTER launch screen is loaded-->
<style name="AppThemeBase" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="toolbarStyle">@style/NativeScriptToolbarStyle</item>
    <item name="colorPrimary">@color/ns_primary</item>
    <item name="colorPrimaryDark">@color/ns_primaryDark</item>
    <item name="colorAccent">@color/ns_accent</item>
    <item name="android:statusBarColor">@color/transparent</item>
    <item name="android:navigationBarColor">@color/transparent</item>

    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:windowTranslucentNavigation">false</item>
</style>

<style name="AppTheme" parent="AppThemeBase"></style>

<!-- theme for action-bar -->
<style name="NativeScriptToolbarStyleBase" parent="Widget.AppCompat.Toolbar">
    <item name="android:background">@color/transparent</item>
    <item name="theme">@color/transparent</item>
    <item name="popupTheme">@color/transparent</item>
</style>

<style name="NativeScriptToolbarStyle" parent="NativeScriptToolbarStyleBase"></style>

Took me about 2-3 days to figure out, hope this helps

Upvotes: 0

Machado
Machado

Reputation: 14489

Update

You can achieve the same effect programmatically on KitKat and afterward by setting the FLAG_LAYOUT_NO_LIMITS flag inside the Window.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Window w = getWindow(); // in Activity's onCreate() for instance
            w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
        }

If you set a background resource (like a color or a picture) to your layout, you will see the color or picture "below" the status bar.

<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@color/primary_dark</item>

Original Answer

It looks like android:windowTranslucentStatus and android:windowTranslucentNavigation should be true instead of false

<resources>
    <style name="Theme" parent="android:Theme.Material.Wallpaper.NoTitleBar">
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:navigationBarColor">@android:color/transparent</item>
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">true</item>
    </style>
</resources>

Also, your transparent activity / container layout needs this property set:

android:fitsSystemWindows="true"

[Source][1] [1]: https://stackoverflow.com/a/29311321/1549700

Upvotes: 163

Mathias
Mathias

Reputation: 213

For API 29 and above use

<style name="Your.Theme">
    <item name="android:navigationBarColor">@android:color/transparent</item>
    <item name="android:enforceNavigationBarContrast">false</item>
</style>

Upvotes: 18

Arpan Sarkar
Arpan Sarkar

Reputation: 2406

You can use this kotlin extension function it will set status bar fully transparent (on API 23+, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR flag available on API 23+) and navigation bar (on API 27+, View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR flag available on API 27+) otherwise it will use the systemUiScrim color on API 21+

fun Activity.transparentStatusAndNavigation(
    systemUiScrim: Int = Color.parseColor("#40000000") // 25% black
) {
    var systemUiVisibility = 0
    // Use a dark scrim by default since light status is API 23+
    var statusBarColor = systemUiScrim
    //  Use a dark scrim by default since light nav bar is API 27+
    var navigationBarColor = systemUiScrim
    val winParams = window.attributes


    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        systemUiVisibility = systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
        statusBarColor = Color.TRANSPARENT
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        systemUiVisibility = systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
        navigationBarColor = Color.TRANSPARENT
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        systemUiVisibility = systemUiVisibility or
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
        window.decorView.systemUiVisibility = systemUiVisibility
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        winParams.flags = winParams.flags or
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS or
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        winParams.flags = winParams.flags and
                (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS or
                        WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION).inv()
        window.statusBarColor = statusBarColor
        window.navigationBarColor = navigationBarColor
    }

    window.attributes = winParams
}

API 21+ API 21+ API 27+ API 27+

Upvotes: 16

Ahamadullah Saikat
Ahamadullah Saikat

Reputation: 4644

100% working code

Completely Transparent StatusBar and NavigationBar

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    initStatusNavBar();
    transparentStatusAndNavigation();

    showSystemUI();
    // hideSystemUI();

}

public static void transparentStatusAndNavigation(Activity activity) {

    Window window = activity.getWindow();

    // make full transparent statusBar
    if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
        setWindowFlag(window, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, true);
    }
    if (Build.VERSION.SDK_INT >= 19) {
        int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
        visibility = visibility | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
        window.getDecorView().setSystemUiVisibility(visibility);
    }
    if (Build.VERSION.SDK_INT >= 21) {
        int windowManager = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
        windowManager = windowManager | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
        setWindowFlag(window, windowManager, false);
        window.setStatusBarColor(Color.TRANSPARENT);
        window.setNavigationBarColor(Color.TRANSPARENT);
    }

}

private static void setWindowFlag(final int bits, boolean on) {
    Window win = getWindow();
    WindowManager.LayoutParams winParams = win.getAttributes();
    if (on) {
        winParams.flags |= bits;
    } else {
        winParams.flags &= ~bits;
    }
    win.setAttributes(winParams);
}

Set StatusBar & NavigationBar height & Color:

in activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mainLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical">

    <View
        android:id="@+id/status_bg"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="@color/primaryColorLightThemeDarkTrans"
        tools:layout_height="24dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <!--Write Code Here-->

    </LinearLayout>

    <View
        android:id="@+id/nav_bg"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="@color/navColorLightThemeTrans"
        tools:layout_height="?actionBarSize" />
</LinearLayout>

in java code:

private void initStatusNavBar() {
    int statusBarHeight = getStatusBarHeight(activity);
    int navBarHeight = getNavigationBarHeight(activity, statusBarHeight);

    View statusBarBackground = findViewById(R.id.status_bg);
    statusBarBackground.getLayoutParams().height = statusBarHeight;

    View navBarBackground = findViewById(R.id.nav_bg);
    if (Build.VERSION.SDK_INT >= 21) {
        setNavigationBarHeight(activity, navBarBackground);
    } else {
        navBarBackground.getLayoutParams().height = navBarHeight;
    }
}

public static int getStatusBarHeight(Activity activity) {
    final Resources resources = activity.getResources();
    final int resId = resources.getIdentifier("status_bar_height", "dimen", "android");
    if (resId > 0) {
        return resources.getDimensionPixelSize(resId);
    }
    return 0;
}

public static int getNavigationBarHeight(Activity activity, int statusBarHeight) {
    Point point = getNavigationBarSize(activity);
    int height = point.y;
    if (isNotchDisplay(statusBarHeight)) {
        height = height - statusBarHeight;
    }
    return height;
}

private static Point getNavigationBarSize(Context context) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        Point appUsableSize = getAppUsableScreenSize(context);
        Point realScreenSize = getRealScreenSize(context);

        // navigation bar on the right
        if (appUsableSize.x < realScreenSize.x) {
            return new Point(realScreenSize.x - appUsableSize.x, appUsableSize.y);
        }

        // navigation bar at the bottom
        if (appUsableSize.y < realScreenSize.y) {
            return new Point(appUsableSize.x, realScreenSize.y - appUsableSize.y);
        }

        // navigation bar is not present
        return new Point();
    }
    return new Point();
}

private static Point getAppUsableScreenSize(Context context) {
    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Point size = new Point();
    if (null != windowManager) {
        Display display = windowManager.getDefaultDisplay();
        display.getSize(size);
    }
    return size;
}

private static Point getRealScreenSize(Context context) {
    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Point size = new Point();
    if (null != windowManager) {
        Display display = windowManager.getDefaultDisplay();

        if (Build.VERSION.SDK_INT >= 17) {
            display.getRealSize(size);
        } else {
            try {
                size.x = (Integer) Display.class.getMethod("getRawWidth").invoke(display);
                size.y = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
    }

    return size;
}

private static boolean isNotchDisplay(int statusBarHeight) {
    int normalStatusBarHeight = dpToPxForNav(25);
    return statusBarHeight > normalStatusBarHeight;
}

private static int dpToPxForNav(float dp) {
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return Math.round(px);
}

public static void setNavigationBarHeight(Activity activity, View navBarBackground) {
    ViewCompat.setOnApplyWindowInsetsListener(navBarBackground, (v, insets) -> {
        int navBarHeight = insets.getSystemWindowInsetBottom();
        navBarBackground.getLayoutParams().height = navBarHeight;
        return insets.consumeSystemWindowInsets();
    });
}


@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void showSystemUI() {
    statusBarBackground.setVisibility(View.VISIBLE);
    navBarBackground.setVisibility(View.VISIBLE);
    mDecorView.setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void hideSystemUI() {
    statusBarBackground.setVisibility(View.GONE);
    navBarBackground.setVisibility(View.GONE);
    mDecorView.setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                    | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}

Theme at styles.xml:

<style name="MyAppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">

    <!--For Notch Issues-->
    <item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">shortEdges</item>

    <item name="windowActionBarOverlay">true</item>

    <item name="colorPrimary">@color/primaryColor</item>
    <item name="colorPrimaryDark">@color/primaryColorDark</item>
    <item name="colorAccent">@color/accentColor</item>
    <item name="colorControlHighlight">@color/colorHighlight</item>
    <item name="android:windowBackground">@android:color/white</item>
    <item name="android:textColorPrimary">#fff6d7</item>

    <item name="android:colorPrimary" tools:targetApi="lollipop">@color/primaryColor</item>
    <item name="android:colorPrimaryDark" tools:targetApi="lollipop">@color/primaryColorDark</item>
    <item name="android:statusBarColor" tools:targetApi="lollipop">@color/primaryColorDark</item>
    <item name="android:colorAccent" tools:targetApi="lollipop">@color/accentColorLight</item>
    <item name="android:colorControlHighlight" tools:targetApi="lollipop">@color/colorHighlight</item>

    <item name="android:navigationBarColor" tools:targetApi="lollipop">@color/navColor</item>

    <item name="android:windowTranslucentStatus" tools:targetApi="kitkat">true</item>
    <item name="android:windowActionBarOverlay">true</item>
    <item name="android:windowTranslucentNavigation" tools:targetApi="kitkat">true</item>

</style>

in AndroidManifest.xml:

    <activity
        android:name="com.MyActivity"
        android:configChanges="orientation|keyboardHidden|screenSize"
        android:screenOrientation="fullSensor"
        android:theme="@style/MyAppTheme" />

Upvotes: 4

Dinu Nicolae
Dinu Nicolae

Reputation: 1281

You can also change the alpha of your colorPrimary and colorPrimaryDark to 00 and then add this to your onCreateMethod:

    window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

and also add this to your activity:

android:fitsSystemWindows="true"

Upvotes: 0

Thomas Gorisse
Thomas Gorisse

Reputation: 904

To draw your layout under statusbar :

values/styles.xml

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

values-v21/styles.xml

<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@color/colorPrimaryDark</item>

Use CoordinatorLayout/DrawerLayout which already take care of the fitsSystemWindows parameter or create your own layout to like this:

public class FitsSystemWindowConstraintLayout extends ConstraintLayout {

    private Drawable mStatusBarBackground;
    private boolean mDrawStatusBarBackground;

    private WindowInsetsCompat mLastInsets;

    private Map<View, int[]> childsMargins = new HashMap<>();

    public FitsSystemWindowConstraintLayout(Context context) {
        this(context, null);
    }

    public FitsSystemWindowConstraintLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FitsSystemWindowConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        if (ViewCompat.getFitsSystemWindows(this)) {
            ViewCompat.setOnApplyWindowInsetsListener(this, new android.support.v4.view.OnApplyWindowInsetsListener() {
                @Override
                public WindowInsetsCompat onApplyWindowInsets(View view, WindowInsetsCompat insets) {
                    FitsSystemWindowConstraintLayout layout = (FitsSystemWindowConstraintLayout) view;
                    layout.setChildInsets(insets, insets.getSystemWindowInsetTop() > 0);
                    return insets.consumeSystemWindowInsets();
                }
            });
            setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
            TypedArray typedArray = context.obtainStyledAttributes(new int[]{android.R.attr.colorPrimaryDark});
            try {
                mStatusBarBackground = typedArray.getDrawable(0);
            } finally {
                typedArray.recycle();
            }
        } else {
            mStatusBarBackground = null;
        }
    }

    public void setChildInsets(WindowInsetsCompat insets, boolean draw) {
        mLastInsets = insets;
        mDrawStatusBarBackground = draw;
        setWillNotDraw(!draw && getBackground() == null);

        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                if (ViewCompat.getFitsSystemWindows(this)) {
                    ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) child.getLayoutParams();

                    if (ViewCompat.getFitsSystemWindows(child)) {
                        ViewCompat.dispatchApplyWindowInsets(child, insets);
                    } else {
                        int[] childMargins = childsMargins.get(child);
                        if (childMargins == null) {
                            childMargins = new int[]{layoutParams.leftMargin, layoutParams.topMargin, layoutParams.rightMargin, layoutParams.bottomMargin};
                            childsMargins.put(child, childMargins);
                        }
                        if (layoutParams.leftToLeft == LayoutParams.PARENT_ID) {
                            layoutParams.leftMargin = childMargins[0] + insets.getSystemWindowInsetLeft();
                        }
                        if (layoutParams.topToTop == LayoutParams.PARENT_ID) {
                            layoutParams.topMargin = childMargins[1] + insets.getSystemWindowInsetTop();
                        }
                        if (layoutParams.rightToRight == LayoutParams.PARENT_ID) {
                            layoutParams.rightMargin = childMargins[2] + insets.getSystemWindowInsetRight();
                        }
                        if (layoutParams.bottomToBottom == LayoutParams.PARENT_ID) {
                            layoutParams.bottomMargin = childMargins[3] + insets.getSystemWindowInsetBottom();
                        }
                    }
                }
            }
        }

        requestLayout();
    }

    public void setStatusBarBackground(Drawable bg) {
        mStatusBarBackground = bg;
        invalidate();
    }

    public Drawable getStatusBarBackgroundDrawable() {
        return mStatusBarBackground;
    }

    public void setStatusBarBackground(int resId) {
        mStatusBarBackground = resId != 0 ? ContextCompat.getDrawable(getContext(), resId) : null;
        invalidate();
    }

    public void setStatusBarBackgroundColor(@ColorInt int color) {
        mStatusBarBackground = new ColorDrawable(color);
        invalidate();
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mDrawStatusBarBackground && mStatusBarBackground != null) {
            int inset = mLastInsets != null ? mLastInsets.getSystemWindowInsetTop() : 0;
            if (inset > 0) {
                mStatusBarBackground.setBounds(0, 0, getWidth(), inset);
                mStatusBarBackground.draw(canvas);
            }
        }
    }
}

main_activity.xml

<FitsSystemWindowConstraintLayout 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">

    <ImageView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:fitsSystemWindows="true"
        android:scaleType="centerCrop"
        android:src="@drawable/toolbar_background"
        app:layout_constraintBottom_toBottomOf="@id/toolbar"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="0dp"
        android:layout_height="?attr/actionBarSize"
        android:background="@android:color/transparent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/toolbar">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="Content"
            android:textSize="48sp" />
    </LinearLayout>
</FitsSystemWindowConstraintLayout>

Result :

result

Upvotes: 1

Dasser Basyouni
Dasser Basyouni

Reputation: 3252

For those who want a completely transparent status bar and navigation bar on KitKat and up there is a small conflict with using windowTranslucentNavigation with @Machado answer's for Lollipop and to prevent that conflict separate the styles

styles.xml

<style name="LockScreenStyle" parent="@android:style/Theme.Wallpaper.NoTitleBar">
    <item name="android:windowTranslucentStatus" tools:targetApi="kitkat">true</item>
    <item name="android:windowTranslucentNavigation" tools:targetApi="kitkat">true</item>
</style>

styles.xml (v21)

<style name="LockScreenStyle" parent="@android:style/Theme.Wallpaper.NoTitleBar">
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>

MyClass.java

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        Window w = getWindow(); // in Activity's onCreate() for instance
        w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
                WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

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

Upvotes: 0

denixtry
denixtry

Reputation: 3098

I use this since it keeps the height of the status bar and nav bar

<!-- Base application theme. -->
<style name="theme" parent="android:Theme.Material.Wallpaper.NoTitleBar">
    <item name="android:navigationBarColor">#00000000</item>
    <item name="android:statusBarColor">#00000000</item>
</style>

This does require API 21+ however

Upvotes: 9

Wayne
Wayne

Reputation: 6449

You need to add android:windowDrawsSystemBarBackgrounds flag to you theme

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

Or call this in onCreate()

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

Upvotes: 4

Lennon Spirlandelli
Lennon Spirlandelli

Reputation: 3193

The following code is an example of what I use in my project:

styles.xml

<style name="FadingActionBarTheme" parent="@android:style/Theme.Holo.Light.DarkActionBar">
    <item name="android:actionBarStyle">@style/FadingActionBarWidget</item>
</style>

<style name="FadingActionBarWidget.Transparent">
    <item name="android:background">@android:color/transparent</item>
</style>

<style name="FadingActionBarTheme.TranslucentActionBar">
    <item name="android:icon">@drawable/ic_ab_icon</item>
    <item name="android:actionBarStyle">@style/FadingActionBarWidget.Transparent</item>
    <item name="android:windowActionBarOverlay">true</item>
    <item name="android:windowContentOverlay">@null</item>
</style>

AndroidManifest.xml

<activity
    android:name=".MyActivity"
    android:label="@string/app_name"
    android:theme="@style/FadingActionBarTheme.TranslucentActionBar">
</activity>

Upvotes: 4

Related Questions