15

我正在研究一种使状态栏完全透明而不是半透明并且导航栏保持不变的方式。

我能得到的最接近的是使用旗帜

WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS

但这也吸引了导航栏。

背景是什么让这变得棘手,它是一个微妙的渐变,当我将状态栏颜色设置为渐变的开始时,它看起来几乎正确,但在屏幕顶部有一条微妙的线条。

有没有一种让活动适合窗口的好方法,只在顶部,但如果底部有导航栏,不要管它?

4

2 回答 2

27

一个好的方法是来自this answer的方法一。

要实现完全透明的状态栏,您必须使用 statusBarColor,它仅在 API 21 及更高版本上可用。windowTranslucentStatus在 API 19 及更高版本上可用,但它为状态栏添加了有色背景。但是,设置 windowTranslucentStatus确实实现了将statusBarColor更改为透明不能实现的一件事:它设置了 SYSTEM_UI_FLAG_LAYOUT_STABLE 和 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 标志。获得相同效果的最简单方法是手动设置这些标志,这有效地禁用了 Android 布局系统强加的插入,让您自己照顾。

您在 onCreate 方法中调用此行:

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

请务必在 /res/values-v21/styles.xml 中设置透明度:

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

或以编程方式设置透明度:

getWindow().setStatusBarColor(Color.TRANSPARENT);

这种方法的好处是,相同的布局和设计也可以在 API 19 上使用,方法是将透明状态栏换成有色半透明状态栏。

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

我猜你已经尝试过这个或类似的东西。如果这不起作用,请确保您的根元素是FrameLayout.

于 2015-10-26T20:35:36.953 回答
3

免责声明:这是补充答案,因为接受的答案在 API 级别 30 之前有效且不被弃用,因为系统可见性标志自 API 级别 30 起已弃用。

setDecorFitsSystemWindows()为您的应用程序实现边缘到边缘(即应用程序将扩展其内容以扩展到整个屏幕以覆盖系统状态和导航栏)

这可以通过以下方式在活动中实现:

WindowCompat.setDecorFitsSystemWindows(window, false)

现在剩下的部分是避免与系统导航栏重叠:

根据文档:

您可以通过对插图做出反应来解决重叠问题,插图指定屏幕的哪些部分与系统 UI 相交,例如导航栏或状态栏。相交可能意味着简单地显示在内容之上,但它也可以通知您的应用程序有关系统手势的信息。

因此,我们需要处理 API 级别 30+ 的插图,以避免应用程序和底部导航栏之间的重叠:

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

}

检查文档以获取更多信息。

额外分:

  • 如果您打算使用<item name="android:windowTranslucentStatus">true</item>较低的 API 级别,那么您必须覆盖 API-30 中的主题/样式;即具有res\values-v30\themes.xml默认样式(当然没有windowTranslucentStatus
于 2021-10-24T18:27:47.813 回答