透明状态栏(带可见导航栏)

Transparent status bar (with visible navigation bar)

我知道这个问题已经被问过很多次了,但是所有的答案要么不起作用,要么使用了不推荐使用的代码:

我想达到与最新 google 地图应用相同的效果:

WindowCompat.setDecorFitsSystemWindows(window, false) 部分工作,因为它还隐藏了导航栏

我通过以下方法取得了类似的结果。

    <style name="Theme.WebImageDownloader" parent="Theme.MaterialComponents.DayNight.NoActionBar">
     
    // make status bar icons colour grey
    <item name="android:windowLightStatusBar">true</item>
    // override the notch area
    <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
    // make status bar transparent
    <item name="android:windowTranslucentStatus">true</item>
    // make navigation are transparent
    <item name="android:windowTranslucentNavigation">true</item>
   </style>

并在清单中设置以上主题

 android:theme="@style/Theme.WebImageDownloader">

此外,我已经将我的工具栏放在activity中,如下所示,

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@android:color/holo_blue_dark"
android:layout_height="match_parent">

// other views 

<androidx.appcompat.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="32dp"
    android:minHeight="?attr/actionBarSize"
    android:theme="@style/ToolBarStyle" />

</RelativeLayout>

有'ToolBarStyle',你可以为背景、文字等设置任何颜色

要使 StatusBar 完全透明,

首先,在主题中或通过代码将其颜色设置为透明:

//In Theme
<item name="android:statusBarColor">@android:color/transparent</item>
//In Code
window.statusBarColor = android.R.color.transparent

然后,要绘制 StatusBar 后面的视图,请使用此代码:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    window.setDecorFitsSystemWindows(false)
} else {
    window.setFlags(
        WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
        WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
    )
}

你也可以玩boolean 属性 android:windowLightStatusBar,它将StatusBar的文本和图标颜色设置为黑色或白色,你可以做到也以编程方式。如果你不想隐藏它,你也可以为你的 NavigationBar 设置颜色。

输出:

第一步: 使状态栏透明:在样式中添加以下内容 themes.xmlsytles.xml:

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

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

第2步:然后在activity使状态栏与activity重叠:

使用的 window 标志从 API 级别 30 开始被弃用,因此它们可以在 API 级别 29 之前使用:

if (Build.VERSION.SDK_INT in 21..29) { 
    window.statusBarColor = Color.TRANSPARENT
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
    window.decorView.systemUiVisibility =
        SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or SYSTEM_UI_FLAG_LAYOUT_STABLE

} else if (Build.VERSION.SDK_INT >= 30) {
    window.statusBarColor = Color.TRANSPARENT
    // Making status bar overlaps with the activity
    WindowCompat.setDecorFitsSystemWindows(window, false)
}

更新 API-30

This doesn't actually make the status bar transparent, it makes it translucent and will still have a shadow to it

这在 API-30 上是正确的,原因是设置 <item name="android:windowTranslucentStatus">true</item>.

实际上 <item name="android:windowTranslucentStatus">true</item> 仅在 API 级别 19 上需要。如果您的应用大于此级别,则完全可以忽略它。

无论如何,解决这个问题的方法是覆盖 API-30 中的主题。xml/styles.xml;即有一个 res\values-v30\themes.xml;您可以添加主应用主题,例如:

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.TransparentStatusBar" parent="Theme.MaterialComponents.DayNight.NoActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
     </style>
</resources>

更新 2 API-30

刚刚在 API 30 上发现了一个错误,底部导航与 activity 重叠,遮住了它的底部,OP 可能无法发现,因为他们使用的是地图。

为了解决这个问题,As per documentation:

You can address overlaps by reacting to insets, which specify which parts of the screen intersect with system UI such as the navigation bar or the status bar. Intersecting can mean simply being displayed above the content, but it can also inform your app about system gestures, too.

因此,我们需要处理 API 级别 30+ 的系统栏插入,以避免您的应用与导航栏重叠:

这需要 activity 布局的顶根 ViewGroup,因此 LayoutParams 需要适当地倾斜。

我在这里使用 ConstraintLayout 作为根布局,并且 FrameLayout.LayoutParams:

/*
*  Making the Navigation system bar not overlapping with the activity
*/
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
    }

}

这是在 API 19 级到 API 30 级范围内的 8 devices/emulators 上测试的。

private fun setStatusBar() {
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        window.setFlags(
            WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
            WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
        )
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        window.statusBarColor = Color.TRANSPARENT
        window.navigationBarColor = Color.TRANSPARENT
        window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    }

经过几天的搜索,几乎阅读了所有与 Whosebug 相关的帖子。我点击了以下对我有用的设置。因为我只是玩玩然后突然 运行 进去了,所以我不知道为什么它会起作用。

SDK: minSdkVersion 28 targetSdkVersion 30

因此,大多数建议都使用了已弃用的 API,并且很可能是这样的:

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

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

        <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>

以及我通过这些设置得到的结果: 1

然后是那个灰色的状态栏,我看到很多人和我一样,想要摆脱它。

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

我禁用了 t运行slucentStatus,并使用代码处理状态栏后面的显示:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setTheme(R.style.Theme_MyApp);
        getWindow().setDecorFitsSystemWindows(false);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_log_in);

之后我得到了这个结果: 2

最后,我们更改状态栏文字颜色:

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

它有效: 3

:)

将此添加到您的主题

<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowLightStatusBar" ns1:targetApi="23">true</item>

并使用这个方法

     private fun handleStatusBar() {
        //set fullScreen (draw under statusBar and NavigationBar )
            WindowCompat.setDecorFitsSystemWindows(window, false)

            container.setOnApplyWindowInsetsListener { view, insets ->
            val navigationBarHeight = WindowInsetsCompat.toWindowInsetsCompat(insets)
                .getInsets(WindowInsetsCompat.Type.navigationBars()).bottom

            view.updatePadding(bottom = navigationBarHeight)
            WindowInsetsCompat.CONSUMED.toWindowInsets()
        }

        //make statusBar content dark
        WindowCompat.getInsetsController(window, window.decorView)?.isAppearanceLightStatusBars =
            true

        window.statusBarColor = Color.TRANSPARENT
    }

我在 onCreate 中为我的应用程序执行此操作

with(window) {
        setFlags(
            WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
            WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
        )
    }

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

我已经尝试了所有不同 android 版本的答案.. 对我有用的是:

  • 不要将android:windowTranslucentStatus设置为true,它会使状态栏透明但有黑色阴影。
// no need to add this.. it is false in default
<item name="android:windowTranslucentStatus">false</item>
  • 在您的 activity 中调用此方法使状态栏透明,即使对于 android 11 和 12
public void transparentStatusBar() {
        Window window = getWindow();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            window.setDecorFitsSystemWindows(false);
        } else {
            window.setFlags(
                    WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
                    WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
            );
        }
        window.setStatusBarColor(Color.TRANSPARENT);
}
  • 如果您发现导航栏覆盖底部视图..只需在底部添加填充并避免这种情况:)
  • 设置状态栏色调为黑色
<item name="android:windowLightStatusBar" tools:targetApi="M">true</item>