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

Posted

技术标签:

【中文标题】透明状态栏(带可见导航栏)【英文标题】:Transparent status bar (with visible navigation bar) 【发布时间】:2021-09-27 18:41:38 【问题描述】:

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

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

我想达到和最新的google maps app一样的效果:

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

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

【问题讨论】:

还在寻找解决方案? @dor506 查看此链接 - ***.com/questions/68506784/… 【参考方案1】:

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

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

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

第二步:然后在activity中让状态栏与activity重叠:

使用的窗口标志从 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 上是正确的,原因是设置 &lt;item name="android:windowTranslucentStatus"&gt;true&lt;/item&gt;

实际上,&lt;item name="android:windowTranslucentStatus"&gt;true&lt;/item&gt; 仅在 API 级别 19 上是必需的。如果您的应用比这更高,您可以完全关闭它。

无论如何,解决这个问题的方法是覆盖 API-30 中的themes.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>

API-30 更新 2

刚刚在 API 30 上发现了一个错误,即底部导航与隐藏其底部的 Activity 重叠,OP 在使用地图时可能无法发现。

要解决这个问题,As per documentation:

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

因此,我们需要处理 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 台设备/模拟器上测试的。

【讨论】:

这实际上并没有使状态栏透明,它使它半透明并且仍然会有阴影 @alfietap 我用这个修复更新了答案。谢谢你通知我。【参考方案2】:

为了使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 设置颜色。

输出:

【讨论】:

【参考方案3】:

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

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

此外,我已将我的工具栏放置在活动中,如下所示,

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

// other views 

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

</RelativeLayout>

有'ToolBarStyle',你可以有任何颜色的背景,文字等。

【讨论】:

感谢您的回答,但不是我想要的【参考方案4】:
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
    

【讨论】:

【参考方案5】:

经过几天的搜索,并且已经阅读了所有与 *** 相关的帖子。我点击了以下对我有用的设置。因为我只是玩了一下,突然碰到它,所以我不知道它为什么会起作用。

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

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

&lt;item name="android:windowTranslucentStatus"&gt;false&lt;/item&gt;

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

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

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

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

&lt;item name="android:windowLightStatusBar"&gt;true&lt;/item&gt;

它的工作原理: 3

:)

【讨论】:

【参考方案6】:

将此添加到您的主题中

<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
    

【讨论】:

【参考方案7】:

我在 onCreate 中为我的应用程序这样做

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

它适用于我,我希望它也适用于你。

【讨论】:

以上是关于透明状态栏(带可见导航栏)的主要内容,如果未能解决你的问题,请参考以下文章

如何使状态栏透明,文本颜色为灰色?

可靠获取状态栏高度解决KitKat半透明导航问题

可靠获取状态栏高度解决KitKat半透明导航问题

Android 半透明状态栏但非半透明导航栏(如果存在)

android导航栏与状态栏颜色及透明度

Android 4.4 沉浸式透明状态栏与导航栏