Android 30及更高版本上的黑暗状态栏不会消失

nhjlsmyf  于 12个月前  发布在  Android
关注(0)|答案(3)|浏览(133)

我有一个Activity,它应该在全屏中托管一个Web视图,状态和导航栏完全沉浸式,因为我不想为状态栏设置颜色。我尝试了S.O的多个片段,我仍然有一个Android 12及以上设备的深色状态栏。我需要一个完全沉浸式的状态和导航栏。通过下面的实现,导航栏按预期显示;状态栏仍然是暗的。
下面是我应用于活动的活动主题:

<style name="FullScreenTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    <item name="android:colorBackground">@null</item>
    <item name="android:windowBackground">@null</item>
    <item name="background">@null</item>
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:navigationBarColor">@android:color/transparent</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:enforceStatusBarContrast" tools:targetApi="q">false</item>
    <item name="android:enforceNavigationBarContrast"  tools:targetApi="q">false</item>
</style>

字符串
下面是Activity的onCreate()函数:

super.onCreate(savedInstanceState)
    WindowCompat.setDecorFitsSystemWindows(window, false)

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
        val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
        windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
        windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
    } else {
        @Suppress("DEPRECATION") // Older API support
        window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE
                or View.SYSTEM_UI_FLAG_LAYOUT_STABLE

                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_FULLSCREEN)
    }


在此之后,我调用setContentView()并继续前进。关于我在这里错过的确切内容,有任何想法吗?最近有没有人遇到类似的问题,并且有(测试)解决方案?

vptzau2j

vptzau2j1#

您面临的问题可能与您没有启用cut-out模式有关(启用剪切模式意味着全屏模式不会为槽口/摄像头保留空间,并且也会在其后面绘制,这将扩展屏幕外围到非常外部的边界)。
这里有一个辅助方法来启用或禁用剪切模式。确保从活动上下文调用它(因为它是一个扩展函数)

@TargetApi(Build.VERSION_CODES.P)
    fun ComponentActivity.cutoutMode(enable: Boolean) {
        if (enable) {
            window.attributes?.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
        } else {
            window.attributes?.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
        }
    }

字符串
示例用法:

[email protected](enable = true) 

//or simply
cutoutMode(enable = true)


如果你想要一个静态的方式来做这件事(在XML中),你可以编辑你的应用的主题(在你的themes.xmlstyles.xml中,无论它在哪里),以包括以下属性:

<item name="android:windowLayoutInDisplayCutoutMode">
    shortEdges <!-- default, shortEdges, or never -->
  </item>


你可以在官方文档中找到更多关于剪切模式的信息:Google's Developer Android- Support display cutouts
如果你仍然无法全屏显示,你可以使用这个帮助器方法:

fun ComponentActivity.hideSystemUI(useDeprecated: Boolean) {
        runOnUiThread {
            if (!useDeprecated) {
                WindowCompat.setDecorFitsSystemWindows(window, false)
                WindowInsetsControllerCompat(window, window.decorView).let { controller ->
                    controller.hide(WindowInsetsCompat.Type.systemBars())
                    controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
                }
            } else {
                val decorView: View = window.decorView
                val uiOptions = decorView.systemUiVisibility
                var newUiOptions = uiOptions
                newUiOptions = newUiOptions or View.SYSTEM_UI_FLAG_LOW_PROFILE
                newUiOptions = newUiOptions or View.SYSTEM_UI_FLAG_FULLSCREEN
                newUiOptions = newUiOptions or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                newUiOptions = newUiOptions or View.SYSTEM_UI_FLAG_IMMERSIVE
                newUiOptions = newUiOptions or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                decorView.systemUiVisibility = newUiOptions
                View.OnSystemUiVisibilityChangeListener { newmode ->
                    if (newmode != newUiOptions) {
                        hideSystemUI(false)
                    }
                }
                window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
                window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)

            }
        }
    }


请注意,您仍然可以使用已弃用的方式来全屏(沉浸式模式)。我个人认为即使它已弃用,它也更容易和更稳定?这就是为什么我不做'if-else' SDK版本检查来选择两种方式之一,我只做:
hideSystemUI(useDeprecated = true)
即使我使用的是Android 14。
希望这对你有帮助:)

ovfsdjhp

ovfsdjhp2#

AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
    setContentView(R.layout.activity_main);
    Utility.darkenStatusBar(this, R.color.yourcolorname);

字符串
创建实用程序类后

public class Utility {
    public static void darkenStatusBar(Activity activity, int color) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

        activity.getWindow().setStatusBarColor(
                darkenColor(ContextCompat.getColor(activity, color)));
     }
  }
  private static int darkenColor(int color) {
    float[] hsv = new float[3];
    Color.colorToHSV(color, hsv);
    hsv[2] *= 0.8f;
    return Color.HSVToColor(hsv);
  }
}

bhmjp9jg

bhmjp9jg3#

正如official guide解释的那样,您应该在OnApplyWindowInsetsListener中执行代码:

override fun onCreate(savedInstanceState: Bundle?) {
    ...

    window.decorView.setOnApplyWindowInsetsListener { view, windowInsets ->
        WindowCompat.setDecorFitsSystemWindows(window, false)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
            val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
            windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
            windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
        } else {
            @Suppress("DEPRECATION") // Older API support
            window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE
                or View.SYSTEM_UI_FLAG_LAYOUT_STABLE

                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_FULLSCREEN)
        }

        view.onApplyWindowInsets(windowInsets)
    }
}

字符串
或者,根据以前的官方指南的解释,在onCreate之外的onWindowFocusChanged中执行代码:

override fun onWindowFocusChanged(hasFocus: Boolean) {
    super.onWindowFocusChanged(hasFocus)

    if (hasFocus) {
        WindowCompat.setDecorFitsSystemWindows(window, false)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
            val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
            windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
            windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
        } else {
            @Suppress("DEPRECATION") // Older API support
            window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE
                or View.SYSTEM_UI_FLAG_LAYOUT_STABLE

                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_FULLSCREEN)
        }
    }
}

相关问题