Android在状态栏后面绘制但不在导航栏后面

DR *_*aus 7 android android-6.0-marshmallow

我正在寻找一种状态栏完全透明,而不是半透明的方式,导航栏保持不变.

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

WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS

但这也是导航栏的背后.

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

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

Ben*_*ane 19

一个好的方法是这个答案的方法一.

要实现完全透明的状态栏,您必须使用 statusBarColor,它仅在API 21及更高版本上可用.windowTranslucentStatus在API 19及更高版本上可用,但它为状态栏添加了一个有色背景.但是,设置 windowTranslucentStatus确实实现了将statusBarColor更改为transparent的一件事:它设置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);
Run Code Online (Sandbox Code Playgroud)

一定要在/res/values-v21/styles.xml中设置透明度:

<item name="android:statusBarColor">@android:color/transparent</item>
Run Code Online (Sandbox Code Playgroud)

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

getWindow().setStatusBarColor(Color.TRANSPARENT);
Run Code Online (Sandbox Code Playgroud)

这种方法的好处在于,通过交换有色半透明状态栏的透明状态栏,也可以在API 19上使用相同的布局和设计.

<item name="android:windowTranslucentStatus">true</item>
Run Code Online (Sandbox Code Playgroud)

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

  • 默认为 android.support.design.widget.CoordinatorLayout 而不是 Frame Layout。这成功了,谢谢 (2认同)

Zai*_*ain 5

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

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

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

WindowCompat.setDecorFitsSystemWindows(window, false)
Run Code Online (Sandbox Code Playgroud)

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

根据文档:

您可以通过对插图做出反应来解决重叠问题,插图指定屏幕的哪些部分与系统 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
    }

}
Run Code Online (Sandbox Code Playgroud)

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

加分:

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