Android 完全透明的状态栏?

Android Completely transparent Status Bar?

我搜索了 文档,但只找到了这个: Link半透明是用哪个做的吧?我想做的是让状态栏完全透明(如下图所示)并向后兼容APK <19:

我的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>

我能做什么:

您需要做的就是在您的主题中设置这些属性:

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

你的activity/你希望有透明状态栏的容器布局需要这个属性设置:

android:fitsSystemWindows="true"

通常不可能在 pre-kitkat 上执行此操作,看起来你可以做到 but some strange code makes it so

编辑:我会推荐这个库:https://github.com/jgilfelt/SystemBarTint 用于大量棒棒糖前状态栏颜色控制。

经过深思熟虑,我了解到完全禁用棒棒糖状态栏和导航栏上的半透明或任何颜色的答案是在 window:

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

不需要其他主题,它会产生如下内容:

在您的 XML 中使用此代码,您将能够在 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">

android:fitsSystemWindows="true" 仅适用于 v21。我们可以在主题 xml 或父布局中设置它 LinearLayoutCoordinateLayout 。 对于低于 v21 的版本,我们无法添加此标志。 请根据需要使用不同的 style.xml 文件创建不同的值文件夹。

在顶部布局中使用 android:fitsSystemWindows="false"

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

不要使用 windowLightStatusBar 而是使用 statusBarColor = @android:color/transparent

在状态栏下绘制布局:

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>

使用已经处理 fitsSystemWindows 参数的 CoordinatorLayout/DrawerLayout 或创建您自己的布局,如下所示:

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>

结果:

截图:

只需将这行代码添加到您的 java 主文件中:

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

这仅适用于 API 级别 >= 21。它适用于我。 这是我的代码 (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
}

状态栏和导航栏完全透明

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

这是一个 kotlin 扩展,可以解决这个问题:

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
    }
}

适用于 Android KitKat 及更高版本(对于那些想要使状态栏透明并且不操纵 NavigationBar 的人,因为所有这些答案也会使 NavigationBar 透明!)

最简单的实现方式:

将这 3 行代码放在 styles.xml (v19) -> 如果您不知道如何使用此 (v19),只需将它们写在您的默认 styles.xml 中,然后使用 alt+enter自动创建:

<item name="android:windowFullscreen">false</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:fitsSystemWindows">false</item>

现在,转到您的 MainActivity Class 并将此方法从 class:

中的 onCreate 中取出
public static void setWindowFlag(Activity activity, final int bits, boolean on) {

    Window win = activity.getWindow();
    WindowManager.LayoutParams winParams = win.getAttributes();
    if (on) {
        winParams.flags |= bits;
    } else {
        winParams.flags &= ~bits;
    }
    win.setAttributes(winParams);
}

然后把这段代码放在Activity的onCreate方法中:

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) {
        getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
    }
    //make fully Android Transparent Status bar
    if (Build.VERSION.SDK_INT >= 21) {
        setWindowFlag(this, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, false);
        getWindow().setStatusBarColor(Color.TRANSPARENT);
    }

就是这样!

试试下面的代码:

private static void setStatusBarTransparent(Activity activity) {
    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);
    }
}

将这些行添加到您的 Activity 之前的 setContentView()

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    Window w = getWindow();
    w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
}

将这两行添加到您的 AppTheme

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

最后一件事你的 minSdkVersion 必须 b 19

minSdkVersion 19

这对我有用:

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

只需进入 MainActivity.java


protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Window g = getWindow();
        g.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

        setContentView(R.layout.activity_main);

    }

共有三个步骤:

1) 只需将此代码段用于您的 OnCreate 方法

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

如果您正在处理 Fragment,则应将此代码段放入 activity 的 OnCreate 方法中。

2) 一定要在 /res/values-v21/styles 中也设置透明度。xml:

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

或者您可以通过编程方式设置透明度:

getWindow().setStatusBarColor(Color.TRANSPARENT);

3) 无论如何你应该在 styles.xml

中添加代码段
<item name="android:windowTranslucentStatus">true</item>

注意: 此方法仅适用于 API 21 岁及以上。

在我的例子中,因为我有一个底部工具栏,我在测试以前的解决方案时遇到了问题,android 系统按钮被我的底部菜单覆盖了 我的解决方案是在 activity:

内添加

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

    // force full screen mode
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);


    setContentView(R.layout.main_activity_container);

您可以使用下面的代码。

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); 
getWindow().setStatusBarColor(Color.TRANSPARENT);

在您的主布局中包含此布局。

toolbar.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/toolbarNav"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent"
        app:contentInsetEnd="0dp"
        app:contentInsetLeft="0dp"
        app:contentInsetRight="0dp"
        app:contentInsetStart="0dp">

        <RelativeLayout
            android:id="@+id/rlBackImageLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/main_background2">  //add your color here

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="@dimen/_40sdp"
                android:layout_marginTop="@dimen/_16sdp"
                android:orientation="horizontal">

                <ImageView
                    android:id="@+id/toolbarIcon"
                    android:layout_width="@dimen/_30sdp"
                    android:layout_height="@dimen/_30sdp"
                    android:layout_gravity="center"
                    android:layout_marginStart="@dimen/_10sdp"
                    android:padding="@dimen/_5sdp"
                    android:src="@drawable/nav_icon" />

                <TextView
                    android:id="@+id/txtTitle"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_gravity="center"
                    android:layout_marginEnd="@dimen/_30sdp"
                    android:fontFamily="@font/muli_semibold"
                    android:gravity="center"
                    android:textColor="#fff"
                    android:textSize="@dimen/_14ssp"
                    android:textStyle="bold"
                    tools:text="test Data" />

            </LinearLayout>

        </RelativeLayout>

    </androidx.appcompat.widget.Toolbar>

注意:SDP和SSP可以分别用dp和sp代替。

在我的例子中,我根本不调用 "onCreate"(它是一个反应本机应用程序,这也可以通过使用反应本机 StatusBar 组件来修复)也可以使用这个:

override fun onStart() {
        super.onStart()
        window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        window.statusBarColor = Color.TRANSPARENT
}

您可以使用以下代码使状态栏透明。 查看带有红色突出显示的图像,这有助于您识别下面代码的使用

您的 android 应用的 Kotlin 代码片段

步骤:1在创建方法中写下代码

if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
    setWindowFlag(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(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, false)
    window.statusBarColor = Color.TRANSPARENT
}

步骤 2: 您需要下面代码中描述的 SetWindowFlag 方法。

private fun setWindowFlag(bits: Int, on: Boolean) {
    val win = window
    val winParams = win.attributes
    if (on) {
        winParams.flags = winParams.flags or bits
    } else {
        winParams.flags = winParams.flags and bits.inv()
    }
    win.attributes = winParams
}

Java 您的 android 应用的代码片段:

第一步:主要Activity代码

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) {
    getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}

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

第二步: SetWindowFlag 方法

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

我在调查这个库时找到了答案: https://github.com/laobie/StatusBarUtil

因此您需要将以下代码添加到您的 activity

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
    window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
    window.statusBarColor = Color.TRANSPARENT
} else {
    window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
}

虽然上面的所有答案都围绕相同的基本思想传播,但您可以使用上面的示例之一将其用于简单的布局。但是,我想在使用滑动 'full screen'(标签栏放在一边)片段导航时更改背景颜色并保持常规导航、标签和操作栏。

仔细阅读后an article by Anton Hadutski我更好地理解了这是怎么回事。

我有 DrawerLayoutConstraintLayout(即容器),其中有 Toolbar,包括主要片段和 BottomNavigationView

DrawerLayoutfitsSystemWindows 设置为 true 是不够的,您需要同时设置 DrawerLayoutConstraintLayout。假设透明状态栏,状态栏颜色现在和ConstraintLayout的背景颜色一样。

但是,包含的片段仍然插入了状态栏,因此在 with 之上设置另一个 'full screen' 片段的动画不会改变状态栏的颜色。

引用文章中的一些代码到 ActivityonCreate:

ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.container)) { view, insets ->
        insets.replaceSystemWindowInsets(
                insets.systemWindowInsetLeft,
                0,
                insets.systemWindowInsetRight,
                insets.systemWindowInsetBottom
        )
    }

一切都很好,除了现在 Toolbar 没有解决状态栏高度问题。更多参考文章,我们有一个完整的解决方案:

val toolbar = findViewById<Toolbar>(R.id.my_toolbar)
    ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.container)) { view, insets ->
        val params = toolbar.layoutParams as ViewGroup.MarginLayoutParams
        params.topMargin = insets.systemWindowInsetTop
        toolbar.layoutParams = params
        insets.replaceSystemWindowInsets(
                insets.systemWindowInsetLeft,
                0,
                insets.systemWindowInsetRight,
                insets.systemWindowInsetBottom
        )
    }

main_activity.xml(请注意Toolbar中的marginTop用于预览目的,将被代码替换):

<?xml version="1.0" encoding="utf-8"?>
    <androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        >

    <androidx.constraintlayout.widget.ConstraintLayout 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/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/green"
        android:fitsSystemWindows="true"
        tools:context=".MainActivity">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/my_toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:layout_constraintTop_toTopOf="@id/container"
            android:layout_marginTop="26dp" 
            android:background="@android:color/transparent"
            ...>
            ...
        </androidx.appcompat.widget.Toolbar>

        <include layout="@layout/content_main" />
        ...
    </androidx.constraintlayout.widget.ConstraintLayout>
    ...
</androidx.drawerlayout.widget.DrawerLayout>

我发现摆弄 styles.xml 和 activity 太麻烦了,因此创建了一个通用的实用方法,其中设置了以下选项

Java

Window window = getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
window.setStatusBarColor(Color.TRANSPARENT);

Kotlin DSL

activity.window.apply {
    clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
    addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
    decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    statusBarColor = Color.TRANSPARENT
}

这就是实现透明状态栏所需要的全部。希望这有帮助。

这应该有效

// 例如在 Activity 的 onCreate() 中

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    Window w = getWindow();
    w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
}

这是 Kotlin 扩展:

fun Activity.transparentStatusBar() {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
        window.statusBarColor = Color.TRANSPARENT

    } else
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)

}

简单明了,适用于几乎所有用例(API 16 级及以上):

  1. 在您的应用主题中使用以下标签使状态栏透明:

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

  2. 然后在 activity 的 onCreate 方法中使用此代码。

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

这就是您需要做的全部 ;)

您可以从 developer documentation. I'd also recommend reading this 博客 post 中了解更多信息。

科特林代码:

    val decorView = window.decorView
    decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)

查看我的另一个答案

以下代码将使您的状态栏和导航栏透明(请注意,这将使您的布局像游戏中使用的布局一样全屏布局):

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {
        hideSystemUI();
    }
}

private void hideSystemUI() {
    // Enables sticky immersive mode.
    // For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE_STICKY.
    // Or for regular immersive mode replace it with SYSTEM_UI_FLAG_IMMERSIVE
    View decorView = getWindow().getDecorView();
    decorView.setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                    // Set the content to appear under the system bars so that the
                    // content doesn't resize when the system bars hide and show.
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    // Hide the nav bar and status bar
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN);
}

要了解更多信息,请访问 this link。

对于 API > 23 Day/Night 支持,您可以使用下面的扩展。要理解的重要部分是 android:fitsSystemWindows="true" 使用填充在插图内移动(就像使用工具栏一样)。因此,将它放置在您的根布局中是没有意义的(除了 DrawerLayout、CoordinatorLayout,...它们使用它们自己的实现)。

<style name="Theme.YourApp.DayNight" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    ...
    <item name="android:windowLightStatusBar">@bool/isDayMode</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>
<androidx.constraintlayout.widget.ConstraintLayout
    ...>

    <com.google.android.material.appbar.MaterialToolbar
        ...
        android:fitsSystemWindows="true">

</androidx.constraintlayout.widget.ConstraintLayout
fun Activity.transparentStatusBar() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
        window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
    } else {
        window.setDecorFitsSystemWindows(false)
    }
}

然后这样称呼它:

class YourActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
        transparentStatusBar()
    }
}

查看 Chris Banes 的这些幻灯片:Becoming a master window fitter

编辑: 如果您对浮动在导航栏后面的内容有疑问,请使用

// using Insetter
binding.yourViewHere.applySystemWindowInsetsToPadding(bottom = true)

以下代码将创建一个完全透明的状态栏:

package com.demo;

import android.app.Activity;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

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

        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) {
            getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
        }
        if (Build.VERSION.SDK_INT >= 21) {
            setWindowFlag(this, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, false);
            getWindow().setStatusBarColor(Color.TRANSPARENT);
        }
    }

    public static void setWindowFlag(Activity activity, final int bits, boolean on) {
        Window win = activity.getWindow();
        WindowManager.LayoutParams winParams = win.getAttributes();
        if (on) {
            winParams.flags |= bits;
        } else {
            winParams.flags &= ~bits;
        }
        win.setAttributes(winParams);
    }
}
<style name="Theme.Transparent" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
</style>

此解决方案适用于那些希望拥有完全透明的 StatusBar 并且 NavigationBar 不受影响的用户。令人难以置信的是,这听起来如此简单,以至于让包括我在内的不止一个人头疼。

这就是我说的最终结果

RESULT

我们只需要两个函数,我建议在 Activity 的 OnCreate 中调用,第一个是 setStatusBar(),即负责对同一个透明化。

private fun setStatusBar() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    window.apply {
        clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            decorView.systemUiVisibility =
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
        } else {
            decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        }
        statusBarColor = Color.TRANSPARENT
    }
}

第二个,setMargins() 负责设置限制在顶部的视图对应的外边距,否则这些视图将显示在下方状态栏。

private fun setMargins() {
    ViewCompat.setOnApplyWindowInsetsListener(
        findViewById(R.id.your_parent_view)
    ) { _, insets ->
        val view = findViewById<FrameLayout>(R.id.your_child_view)
        val params = view.layoutParams as ViewGroup.MarginLayoutParams
        params.setMargins(
            0,
            insets.systemWindowInsetTop,
            0,
            0
        )
        view.layoutParams = params
        insets.consumeSystemWindowInsets()
    }
}

最终代码如下:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.your_layout))
        setStatusBar()
        setMargins()
}

private fun setStatusBar() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    window.apply {
        clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            decorView.systemUiVisibility =
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
        } else {
            decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        }
        statusBarColor = Color.TRANSPARENT
    }
}

private fun setMargins() {
    ViewCompat.setOnApplyWindowInsetsListener(
        findViewById(R.id.your_parent_view)
    ) { _, insets ->
        val view = findViewById<FrameLayout>(R.id.your_child_view)
        val params = view.layoutParams as ViewGroup.MarginLayoutParams
        params.setMargins(
            0,
            insets.systemWindowInsetTop,
            0,
            0
        )
        view.layoutParams = params
        insets.consumeSystemWindowInsets()
    }
}

您可以在下面找到所有这些的更详细解释 Post

我还留下了 Test Project 这些概念起作用的地方。

如果您使用的是 React Native,则其他帖子无效。 React 有自己的处理方式。

<StatusBar translucent backgroundColor="transparent" />react-native 是要走的路,感谢 this post 这将覆盖应用程序中的 android 设置。

但是,有两件事要知道:

  1. 如果您正在使用 react-native-elements 中的 <Header /> 组件,它已经包含 <StatusBar />,请改用其 statusBarProps
  2. 如果你使用的是WIX react-native-navigation,他们有单独的方法来处理状态栏,参考this and this。他们说它与 React Native 不兼容,但是,看起来它们对我来说工作得很好。

刚找到here

因为已经过去6年了,默认的minSDKAPI是21 (Lollipop) *CMIIW。这是我总结透明状态栏并且不与导航按钮重叠的方法:

fun setStatusBarTransparent(activity: Activity, view: View) {
    activity.apply {
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        window.statusBarColor = ContextCompat.getColor(this, R.color.transparent)
        WindowCompat.setDecorFitsSystemWindows(window, false)
        ViewCompat.setOnApplyWindowInsetsListener(view) { root, windowInset ->
            val inset = windowInset.getInsets(WindowInsetsCompat.Type.systemBars())
            root.updateLayoutParams<ViewGroup.MarginLayoutParams> {
                leftMargin = inset.left
                bottomMargin = inset.bottom
                rightMargin = inset.right
            }
            WindowInsetsCompat.CONSUMED
        }
    }
}

我将该函数放在 Object class 中,称为 UiUtils,所以当我在我的 activity 中调用该函数时(我也使用视图绑定)。它看起来像这样:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    ...
    UiUtils.setStatusBarTransparent(this, bind.root)
    ...
}

希望我的回答能帮到大家:)

这是一个简单的方法,我经过大量搜索后找到它。

Step 1

在你的主题中放入这个项目

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

Step 2

主要Activity

WindowCompat.setDecorFitsSystemWindows(window, false)

非常重要,如果你使用 BottomNavigationBar

在某些设备中,API 30+ 如果在您的应用程序中使用,您会发现系统导航栏与底部导航栏重叠。

这是解决这个问题的方法。

  if (Build.VERSION.SDK_INT >= 30) {
        // Root ViewGroup of my activity
        val root = findViewById<ConstraintLayout>(R.id.root)

        ViewCompat.setOnApplyWindowInsetsListener(root) { view, windowInsets ->

            val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())

            // Apply the insets as a margin to the view. Here the system is setting
            // only the bottom, left, and right dimensions, but apply whichever insets are
            // appropriate to your layout. You can also update the view padding
            // if that's more appropriate.

            view.layoutParams =  (view.layoutParams as FrameLayout.LayoutParams).apply {
                leftMargin = insets.left
                bottomMargin = insets.bottom
                rightMargin = insets.right
            }

            // Return CONSUMED if you don't want want the window insets to keep being
            // passed down to descendant views.
            WindowInsetsCompat.CONSUMED
        }

    }

2022 年最优雅的解决方案:

private fun hideStatusBar() {
    val windowInsetsController = ViewCompat.getWindowInsetsController(window.decorView) ?: return
    windowInsetsController.hide(WindowInsetsCompat.Type.statusBars())
}

它只是删除了状态栏颜色!

window?.decorView?.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
window?.statusBarColor = Color.TRANSPARENT

它对我有用,希望对你也有用