开关状态栏文本颜色/设置外观WindowController的LightStatusBars未按预期工作
我的应用程序使用两种不同的背景,具体取决于哪个屏幕处于活动状态。一般来说,状态栏是透明的,背景应该在它后面。根据背景,我需要将状态栏文本的颜色设置为浅色或深色。
到目前为止,我使用这个主题属性使状态栏变得透明(它真的是半透明的,但如果有人知道如何使它变得透明,我将不胜感激)
<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的测试设备上获得所需结果。
在运行API 30的模拟器上,我现在又遇到了一个问题:
WindowCompat.setDecorFitsSystemWindows(window, false);
让我们在状态栏后面,也在导航栏后面。现在,状态栏按预期工作,但导航栏隐藏了部分用户界面。我需要导航栏处于旧状态,不要被拖到下面。有什么想法吗?
为完整性
compileSdkVersion 31
minSdkVersion 23
targetSdkVersion 31
解决方案
跟随this我能够在测试中获得预期的结果 运行Android 10的设备。在运行API 30的模拟器上,我现在又遇到了一个问题:
WindowCompat.setDecorFitsSystemWindows(window, false);
让我们在状态栏后面,也在导航栏后面。 现在,状态栏按预期工作,但导航栏隐藏了部分 用户界面的。我需要导航栏保持其旧状态,而不是 被画在下面。有什么想法吗?
这是正确的,因为setDecorFitsSystemWindows()
实现了应用程序的边缘到边缘(即,应用程序将覆盖系统状态和导航栏)
但是,As per documentation:
您可以通过对插页做出反应来处理重叠,插页指定了 屏幕的某些部分与系统用户界面相交,如导航 栏或状态栏。相交可以简单地表示显示 在内容之上,但它还可以通知您的应用程序有关系统的信息 手势也一样。
因此,我们需要处理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
}
}
相关文章