Android Completely transparent Status Bar?

2019-01-02 17:28发布

问题:

I've searched the documentation but only found this: Link. Which is used to make the bar translucent? What I'm trying to do is to make the status bar completely transparent (as shown in the image below) and make it backwards compatible for APK<19:

My styles.xml:

<resources xmlns:tools="http://schemas.android.com/tools">

  <style name="AppTheme" parent="Theme.AppCompat.Light">
  <item name="android:actionBarStyle">@style/ThemeActionBar</item>
  <item name="android:windowActionBarOverlay">true</item>
  <!-- Support library compatibility -->
  <item name="actionBarStyle">@style/ThemeActionBar</item>
  <item name="windowActionBarOverlay">true</item>
  </style>

  <style name="ThemeActionBar" parent="Widget.AppCompat.Light.ActionBar.Solid">
  <item name="android:background"> @null </item>
  <!-- Support library compatibility -->
  <item name="background">@null</item>
  <item name="android:displayOptions"> showHome | useLogo</item>
  <item name="displayOptions">showHome|useLogo</item>

  </style>

</resources>

What I was able to do:

回答1:

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

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

Your activity / container layout you wish to have a transparent status bar needs this property set:

android:fitsSystemWindows="true"

It is generally not possible to perform this for sure on pre-kitkat, looks like you can do it but some strange code makes it so.

EDIT: I would recommend this lib: https://github.com/jgilfelt/SystemBarTint for lots of pre-lollipop status bar color control.

Well after much deliberation I've learned that the answer to totally disabling the translucency or any color placed on the status bar and navigation bar for lollipop is to set this flag on 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);
        }

No other theme-ing is necessary, it produces something like this:



回答2:

Just add this line of code to your main java file:

getWindow().setFlags(
    WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
    WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
);


回答3:

You can use the external library StatusBarUtil:

Add to your module level build.gradle:

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

Then you can use the following util for an Activity to make the status bar transparent:

StatusBarUtil.setTransparent(Activity activity)

Example:



回答4:

Use android:fitsSystemWindows="false" in your top layout



回答5:

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 :

Screenshot



回答6:

Never mind I found a answer here: completely transparent status bar and navigation bar on lollipop

Hope it helps someone :).

Now I only need to make it backward compaitable.



回答7:

using this code in ur xml, you will be able to see time bar in ur activity :

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">


回答8:

Completely Transparent StatusBar and NavigationBar

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

    transparentStatusAndNavigation();
}


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

private 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);
}


回答9:

Here is a extension in kotlin that do the trick:

fun Activity.setTransparentStatusBar() {
    window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        window.statusBarColor = Color.TRANSPARENT
    }
}


回答10:

android:fitsSystemWindows="true" only work on v21. We can set it in theme xml or in parent layout like LinearLayout or in CoordinateLayout . For below v21, We could not add this flag. Please create different values folder with different style.xml file as per your need.



回答11:

This is only for API Level >= 21. It works for me. Here is my code (Kotlin)

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<View>(android.R.id.content).systemUiVisibility =
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
}


回答12:

Has some problems in case with CollapsingToolbarLayout and Soft KeyBoard working. But now always work with adjustPan instaed adjustResize

Here my repository sample



回答13:

 <item name="android:statusBarColor" tools:targetApi="lollipop">@android:color/transparent</item>
            <!--<item name="android:windowLightStatusBar" tools:targetApi="m">true</item>-->

Dont use windowLightStatusBar use instead statusBarColor = @android:color/transparent



标签: