透明状态栏(具有可见导航栏)

2022-09-20 00:00:00 android statusbar

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

  • Android Completely transparent Status Bar?
  • Transparent status bar - before Android 4.4 (KitKat)
  • Lollipop : draw behind statusBar with its color set to transparent

我想达到与最新谷歌地图应用程序相同的效果:

  • 完全透明的状态栏(仅限状态栏。不是导航栏!)
  • 非推荐使用的解决方案

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


解决方案

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

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

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

第二步:然后在活动中使状态栏与活动重叠:

从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更新

这实际上并不会使状态栏变得透明,而是使其变得半透明,并且仍会有阴影

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

实际上<item name="android:windowTranslucentStatus">true</item>只在API级别19上是必需的。如果您的应用程序高于该级别,您可以完全取消它。

无论如何,解决这个问题的方法是覆盖API-30中的hemes.xml/style es.xml;即有一个resvalues-v30 hemes.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>

API-30更新2

刚刚在API 30上发现了一个错误,即底部导航与隐藏底部的活动重叠,这可能无法被操作员发现,因为他们正在使用地图。

若要解决此问题,请As per documentation:

您可以通过对插页做出反应来处理重叠,插页指定了 屏幕的某些部分与系统用户界面相交,如导航 栏或状态栏。相交可以简单地表示显示 在内容之上,但它还可以通知您的应用程序有关系统的信息 手势也一样。

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

这需要活动布局的顶根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个设备/仿真器上进行了测试。

相关文章