Android R隐藏状态栏->向下移动视图,并出现黑色矩形

问题描述

Android R + Pixel 4模拟器:当我隐藏状态栏时,主视图向下移动,黑色正方形(与状态栏大小相同)出现在顶部。 它在Android 11之前运行。 看起来很简单,但我找不到解决方案...而且我需要全屏模式。

我尝试使用SYstem_UI_FLAG_FULLSCREEN(现已弃用)和controller.hide(WindowInsets.Type.statusBars()); 两种方式有相同的问题。

enter image description here

这是主要代码: MainActivity.java

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    Button buttonShow = findViewById(R.id.b1);
    buttonShow.setonClickListener(new View.OnClickListener() {
        public void onClick(View v) {
           showBars();
        }
    });

    Button buttonHide = findViewById(R.id.b2);
    buttonHide.setonClickListener(new View.OnClickListener() {
        public void onClick(View v) {
          hideBars();
        }
    });

    showBars();
}

public void showBars(){

    View decorView = getwindow().getDecorView();
    int uiOptions =  View.SYstem_UI_FLAG_LAYOUT_STABLE
    | View.SYstem_UI_FLAG_LAYOUT_FULLSCREEN;

    decorView.setsystemUIVisibility(uiOptions);

    getwindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    getwindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

    // New code For Android 11,same effect...
    /*
    WindowInsetsController controller = getwindow().getInsetsController();
    if(controller != null) {
        controller.show(WindowInsets.Type.navigationBars());
        controller.show(WindowInsets.Type.statusBars());
        controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
    }*/
}

public void hideBars(){


    View decorView = getwindow().getDecorView();
    int uiOptions = 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_IMMERSIVE;


    decorView.setsystemUIVisibility(uiOptions);

    getwindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    getwindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

    // New code For Android 11,same effect...
    /* WindowInsetsController controller = getwindow().getInsetsController();
      if(controller != null) {
          controller.hide(WindowInsets.Type.navigationBars());
          controller.hide(WindowInsets.Type.statusBars());
          controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
      }*/

}

}

activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:background="@color/purple_200"
    android:id="@+id/layoutMain">


    <Button
        android:id="@+id/b1"
        android:layout_marginTop="200dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="show" />

    <Button
        android:id="@+id/b2"
        android:layout_marginTop="100dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hide"
/>

</RelativeLayout>

解决方法

试试这个代码片段。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_main);
    }
,

我遇到了同样的问题,全屏试试这个:

        fun makeActivityFullScreen(activity: Activity) {
        //set full screen
        activity.window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        activity.window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
        activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        activity.window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
                or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            val attributes = activity.window.attributes
            attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            activity.window.setDecorFitsSystemWindows(true)
        } else {
            hideSystemUI(activity)
        }
    }

    private fun hideSystemUI(activity: Activity) {
        activity.window.decorView.systemUiVisibility = (
                View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
                        View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
                        View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
                        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
                        // Hide the nav bar and status bar
                        View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                        or View.SYSTEM_UI_FLAG_FULLSCREEN)
    }

这是回到正常模式:

        fun makeActivityNormalScreen(activity: Activity) {
        //set normal screen
        activity.window.setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
        activity.window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
                or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
        activity.window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
        activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            val attributes = activity.window.attributes
            attributes.layoutInDisplayCutoutMode = 
    WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            activity.window.setDecorFitsSystemWindows(false)
        } else {
            // Show the system bar
            showSystemUI(activity)
        }
    }

    private fun showSystemUI(activity: Activity) {
        activity.window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_VISIBLE)
    }
,

这对我有用:
使用 v27 配置为您想要的活动创建一个样式资源文件,用于全屏且无剪切:

<style name="Theme.MyApp.ActivityFullscreenNoCutout">
    <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>

并在清单中为您的活动分配样式:

<activity android:name=".MyActivity"
        android:theme="@style/Theme.MyApp.ActivityFullscreenNoCutout"/>

链接:https://developer.android.com/guide/topics/display-cutout

如果您有操作栏/应用栏,则必须将工具栏添加到您的活动中,而不是使用默认工具栏。

链接:https://developer.android.com/training/appbar/setting-up

,

活动代码中的某处...

    @TargetApi(Build.VERSION_CODES.R) 
void hideStatusBar_with_API30() {
    View decorView = getWindow().getDecorView();
    // Order swiped status bar to appear semitransparent.
    // If you do not that
    //  then once appeared bar will not disappear after nor few seconds nor you gesture.
    decorView.getWindowInsetsController().setSystemBarsBehavior(
            WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
    // Hide the status bar.
    decorView.getWindowInsetsController().hide(WindowInsets.Type.statusBars());
    // The status bar is allowed to appear with a swipe gesture.
    // When it is then app layout is resized.
    // To prevent changing the layout,you need to add:
    getWindow().setDecorFitsSystemWindows(false);
    // The status bar will appear over stable layout
}