【问题标题】:Switch Status Bar Text Color / setAppearanceLightStatusBars of WindowController is not working as expectedWindowController 的切换状态栏文本颜色/setAppearanceLightStatusBars 未按预期工作
【发布时间】:2021-12-09 18:55:05
【问题描述】:

我为我的应用程序使用了两种不同的背景,具体取决于哪个屏幕处于活动状态。一般来说,状态栏是透明的,背景应该放在它后面。根据背景,我需要状态栏文本的颜色为浅色或深色。

到目前为止,我使用这个主题属性来让状态栏透明(它确实是半透明的,但如果有人知道如何让它透明,将不胜感激)

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

每当背景像这样切换时,我都会使用 Jetpack 导航来导航并将参数传递给目的地

mNavController.addOnDestinationChangedListener((controller, destination, arguments) -> {
        if (arguments != null) {
            setUseSecondaryBackground(arguments.getBoolean("bg_line_style", false));
        }
});

这真的很好用。现在不起作用的部分是状态栏文字颜色的切换:

private void setUseSecondaryBackground(boolean useLineBackground) {
        if (useLineBackground) {
            //Stuff to switch backgrounds
            windowController.setAppearanceLightStatusBars(false); //Works fine
        } else {
            //Stuff to switch backgrounds

            //Does not work!!! If enabled the whole background is shifted downward by the status bar hight - see pictures
            windowController.setAppearanceLightStatusBars(true);
        }
}

这是使用的控制器,在我的MainActivity 的onCreate() 中创建

windowController = new WindowInsetsControllerCompat(this.getWindow(), this.getWindow().getDecorView());

这里你看到状态栏是绿色的,因为 mainActivity 的背景位于半透明状态栏的后面。 windowController.setAppearanceLightStatusBars(true); 已对此版本发表评论

在这里你看到状态栏是白色的,文本是白色的(因为它仍然是绿色背景)但是它被向下移动并被某种默认的白色状态栏背景取代。查看电池图标现在的位置。 windowController.setAppearanceLightStatusBars(true); 没有评论,在路边某处被处决

更新:

在this 之后,我能够在运行 Android 10 的测试设备上获得所需的结果。

在 Emulator Running API 30 上,我现在还有一个问题:

WindowCompat.setDecorFitsSystemWindows(window, false);

让我们在状态栏和导航栏后面画图。现在状态栏按预期工作,但导航栏隐藏了部分 UI。我需要导航栏处于旧状态,而不是被绘制在下面。有什么想法吗?

为了完整性

compileSdkVersion 31
minSdkVersion 23
targetSdkVersion 31

【问题讨论】:

  • this 可以帮助你
  • 这在一定程度上有所帮助。谢谢,但现在还有一个问题,请参阅上面的编辑

标签: android statusbar android-navigation-bar android-window android-api-30


【解决方案1】:

在this 之后,我能够在我的测试中得到想要的结果 运行 Android 10 的设备。

在 Emulator Running API 30 上,我现在还有一个问题:

WindowCompat.setDecorFitsSystemWindows(window, false);

让我们在状态栏和导航栏后面画图。 现在状态栏按预期工作,但导航栏隐藏了一部分 的用户界面。我需要导航栏处于旧状态而不是 画下。有什么想法吗?

这是对的,因为setDecorFitsSystemWindows() 为您的应用实现了边缘到边缘(即应用将覆盖系统状态栏和导航栏)

但是,As per documentation:

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

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

这需要您的活动布局的顶级根ViewGroup,因此您需要适当地转换LayoutParams。

这里我用的是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经过这么多年仍然不是微不足道的,也不好用。我需要提一下,我之前只使用 API 30 的版本低于 30 就可以使用它。它起作用了。仅使用“旧”方式有什么不好的吗?但是您提供的方式也有效。所以我想我现在保持正确的方式
  • Is there anything bad about just using the "old" way? 它今天对你有用,可能明天;但不幸的是,肯定不会永远工作
猜你喜欢
  • 2021-05-12
  • 2019-03-14
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 2018-12-17
  • 1970-01-01
  • 1970-01-01
  • 2014-02-27
相关资源
最近更新 更多