android - 设置 SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 使下一个 fragment 空白和折叠工具栏在 api <= 27 上不稳定

标签 android android-fragments android-collapsingtoolbarlayout android-architecture-navigation android-statusbar

我用 NavHostFragmentBottomNavigationView带有 5 个标签和 fitsSystemWindows="true" .

描述:

App 对每个 Fragment 都有不同的应用栏设计。例如,在第一个 fragment 应用栏中包含 CollapsingToolbarLayout带有在状态栏下绘制的背景图像,并且在第二个 fragment 应用程序栏中仅包含 Toolbar并且在状态栏下没有绘制任何内容。但是为了让 UI 不会跳动,我只是将所有 fragment 布局设置为使用 fitsSystemWindows="true" .

在第一种情况下,状态栏背景需要透明才能使图像可见,并且其图标的颜色应为白色。但是在第二个 fragment 中,应用栏和状态栏是白色的,图标的颜色应该是深色的。

在 fragment 之间切换时,我使用下面的这两种方法来更改状态栏设置。

private fun setStatusBarBackgroundColor(colorId: Int) {
    window.statusBarColor = ContextCompat.getColor(this, colorId)
}

@RequiresApi(Build.VERSION_CODES.M)
private fun setStatusBarIconsColor(isDark: Boolean) {   // this is causing the issue
    val oldFlags = window.decorView.systemUiVisibility
    var newFlags = oldFlags
    newFlags = if (isDark) {
        newFlags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
    } else {
        newFlags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
    }
    if (newFlags != oldFlags) window.decorView.systemUiVisibility = newFlags
}

问题:

但是,在 android Oreo 及更低版本 (23 >= API <= 27) 上,我注意到在 fragment 之间导航时,它们中的任何一个都可能随时变为空白。之后,所有下一个目的地(甚至导航回来)也都是空白的。仅限 BottomNavigationView可见,内容为NavHostFragment只是空白。但是在 logcat 中,我看到创建了 fragment 并完成了数据提取,等等。虽然没有错误日志

如果我向下滑动以激活 SwipeRefreshLayout,则在空白 fragment 之前当它令人耳目一新时,我尝试滚动,CollapsingToolbarLayout开始表现得很奇怪。滚动事件不会传递给 RecyclerView直到 CollapsingToolbarLayout完全崩溃。然后RecyclerView将开始滚动,但其内容不会在所有可用的垂直空间上绘制,而是像 CollapsingToolbarLayout 一样隐藏在顶部被扩大。

使用 SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 删除方法调用解决问题。但我需要切换状态栏图标的颜色。

最佳答案

Android 团队添加了新的 API 以更轻松地使用 Window API。我不确定 core 的哪个版本图书馆有它们,但我相信从 开始1.5.0 这些 API 可用。我正在使用 androidx.core:core-ktx:1.6.0 .
现在setAppearanceLightStatusBars(boolean isLight) InsetsController 类允许在运行时轻松更改状态栏中图标的外观。
解决方案:

WindowCompat.getInsetsController(window, window.decorView)?.isAppearanceLightStatusBars = isLightStatusBar
注意:在 API 30 及更高版本上,调用此方法有 无影响 如果应用指定了 <item name="android:windowLightStatusBar">true/false</item>AppTheme样式.xml .为了能够在 API 30+ 的运行时切换状态栏图标的颜色,请删除 android:windowLightStatusBar来自 AppTheme
在后台,此方法有 2 种不同的实现,具体取决于 Android 操作系统版本。
API 23-29 的内部实现:
// internal method
public void setAppearanceLightStatusBars(boolean isLight) {
    if (isLight) {
        unsetWindowFlag(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        setWindowFlag(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        setSystemUiFlag(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
    } else {
        unsetSystemUiFlag(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
    }
}
API 30 及更高版本的内部实现:
// internal method
public void setAppearanceLightStatusBars(boolean isLight) {
    if (isLight) {
        mInsetsController.setSystemBarsAppearance(
            WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS,
            WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS);
    } else {
        mInsetsController.setSystemBarsAppearance(
            0,
            WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS);
    }
}

关于android - 设置 SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 使下一个 fragment 空白和折叠工具栏在 api <= 27 上不稳定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59683122/

相关文章:

android - 为什么我得到 "call to OpenGL ES API with no current context"?

android 在线绘制图像

java - Eclipse 项目 "save as"

java - 如何获取当前android设备的时间?

android - 折叠工具栏默认折叠

android - 将应用栏 ScrollView 行为添加到 CoordinatorLayout 中的多个 View

android - TextView 不显示

java - 如何使SearchView与RecyclerView相同?

java - 退出 Activity 时的错误扩展了 FragmentActivity 并包含 ViewPager

java - fragment 不显示在线性布局的框架布局中