在 Android 10 (API 29) 中隐藏状态栏并在应用程序中使用其 space

Hide status bar in Android 10 (API 29) and use its space in the application

我想在Android 10 中隐藏状态栏。我已经阅读了很多类似问题的答案,但它们不适用于我的设备。目标是使用状态栏的 space 作为应用程序视图的一部分:

下面描述的一些解决方案适用于模拟器,但不适用于我的物理设备(Redmi Note 10,API 版本 29)。

如有任何建议,我将不胜感激。

我尝试过的:
我做到了。

我得到了两个结果,但对我来说都不好。

  1. 半透明状态栏。

  1. 完全黑色的状态栏,没有将其 space 用于应用程序视图。

2022 年 5 月 10 日更新:

根据以下答案,无法在 API 29 或更早版本上使用 WindowInsetsController

解决方案 1

@Zain提议。

Activity:

protected void onCreate(Bundle savedInstanceState) {
    ...
    WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
    WindowInsetsControllerCompat windowInsetsCompat = new WindowInsetsControllerCompat(getWindow(), getWindow().getDecorView());
    windowInsetsCompat.hide(WindowInsetsCompat.Type.statusBars());        
    windowInsetsCompat.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
    ...

theme.xml:

<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>

解决方案 2

Activity:

protected void onCreate(Bundle savedInstanceState) {
    ...        
    getWindow().getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LOW_PROFILE
    );        
    ...

theme.xml:

<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>

您需要在您的应用中显示内容 content edge-to-edge (Documentation reference)

第一步: 使用:WindowCompat.setDecorFitsSystemWindows(window, false)

This is the primary step for ensuring that your app goes edge-to-edge, that is, laid out using the entire width and height of the display. Use WindowCompat.setDecorFitsSystemWindows(window, false) to lay out your app behind the system bars, as shown in the following code example:

步骤 2: 使用 WindowInsetsControllerCompat 隐藏状态栏:

    WindowInsetsControllerCompat(window, window.decorView).apply {
        // Hide the status bar
        hide(WindowInsetsCompat.Type.statusBars())
        // Allow showing the status bar with swiping from top to bottom
        systemBarsBehavior =
            WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
    }

第3步:从第1步开始,底部的activity内容将被底部导航栏遮挡;那么您需要使用 WindowInsetsListener:

将 activity 根布局的底部边距调整为导航栏的高度

科特林:

// root layout of your activity
val root = findViewById<ConstraintLayout>(R.id.root)
ViewCompat.setOnApplyWindowInsetsListener(
    root
) { view: View, windowInsets: WindowInsetsCompat ->
    val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
    view.layoutParams = (view.layoutParams as FrameLayout.LayoutParams).apply {
        // draw on top of the bottom navigation bar
        bottomMargin = insets.bottom
    }

    // Return CONSUMED if you don't want the window insets to keep being
    // passed down to descendant views.
    WindowInsetsCompat.CONSUMED
}

Java:

WindowInsetsControllerCompat windowInsetsCompat = new WindowInsetsControllerCompat(getWindow(), getWindow().getDecorView());

windowInsetsCompat.hide(WindowInsetsCompat.Type.statusBars());
windowInsetsCompat.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);

// root layout of your activity
ConstraintLayout root = findViewById(R.id.root);

ViewCompat.setOnApplyWindowInsetsListener(
        root
        , (view, windowInsets) -> {
            Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
            FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
            params.bottomMargin = insets.bottom;
            return WindowInsetsCompat.CONSUMED;
        });

第 4 步: 最后确保您的应用主题允许在剪切区域中绘图:

<item name="android:windowLayoutInDisplayCutoutMode">always</item>

我找到了解决方案。以下行是必需的:

<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>