android:fitsSystemWindows =“true”在使用DrawerLayout和沉浸式模式时存在问题

时间:2016-03-25 19:44:38

标签: android navigation-drawer android-windowmanager android-immersive

尝试使用沉浸式模式并将android:fitsSystemWindows="true"DrawerLayout一起使用时,我遇到了问题。我必须将此设置为true才能将DrawerLayout和工具栏限制为系统栏。

问题是,我有Fragment将应用程序设置为沉浸式模式。这使得应用程序执行此操作: Fullscreen with system bars

我所知道的是android:fitsSystemWindows="true"的已知问题。我将其设置为false,沉浸式模式运行良好,但工具栏和布局的其余部分不再受制于系统条。我尝试在运行时设置值,布局的下半部分(也就是导航栏区域)由我的布局填充,但系统栏区域仍然显示: Fullscreen with status bar

这是我的代码:

activity_main.xml中

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
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:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">

<include
    layout="@layout/app_bar_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

<android.support.design.widget.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    app:headerLayout="@layout/nav_header_main"
    app:menu="@menu/activity_main_drawer" />

</android.support.v4.widget.DrawerLayout>

ClockFragment.java - 隐藏和显示

private void hideSystemUI() {
    if (Build.VERSION.SDK_INT >= 14) {
        getActivity().findViewById(R.id.drawer_layout).setFitsSystemWindows(false);
    }
    getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    if (Build.VERSION.SDK_INT >= 19) {
        mDecorView.setSystemUiVisibility(
                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);
    } else if (Build.VERSION.SDK_INT >= 16) {
        mDecorView.setSystemUiVisibility(
                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);
    } else {
        getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }
    toolbar.setVisibility(View.GONE);
    layoutParams.screenBrightness = -1.00f;
    getActivity().getWindow().setAttributes(layoutParams);
    drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
    uiShowing = false;
    dimming = false;
    screenMode = 1;
}

private void hideSystemUIAndDim() {
    if (Build.VERSION.SDK_INT >= 14) {
        getActivity().findViewById(R.id.drawer_layout).setFitsSystemWindows(false);
    }
    getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    if (Build.VERSION.SDK_INT >= 19) {
        mDecorView.setSystemUiVisibility(
                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);
    } else if (Build.VERSION.SDK_INT >= 16) {
        mDecorView.setSystemUiVisibility(
                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);
    } else {
        getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }
    toolbar.setVisibility(View.GONE);
    layoutParams.screenBrightness = 0.01f;
    getActivity().getWindow().setAttributes(layoutParams);
    drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
    uiShowing = false;
    dimming = true;
    screenMode = 2;
}

private void showSystemUI() {
    if (Build.VERSION.SDK_INT >= 14) {
        getActivity().findViewById(R.id.drawer_layout).setFitsSystemWindows(true);
    }
    if (Build.VERSION.SDK_INT >= 16) {
        mDecorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    } else {
        getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

    }
    toolbar.setVisibility(View.VISIBLE);
    layoutParams.screenBrightness = -1.00f;
    getActivity().getWindow().setAttributes(layoutParams);
    drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
    uiShowing = true;
    dimming = false;
    screenMode = 0;
}

2 个答案:

答案 0 :(得分:8)

好的,我终于解决了我的问题。事实证明我需要添加FLAG_FULLSCREEN标志。这是我未来观众的固定代码:

private void hideSystemUI() {
    if (Build.VERSION.SDK_INT >= 14) {
        drawerLayout.setFitsSystemWindows(false);
    }
    getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
            | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    if (Build.VERSION.SDK_INT >= 19) {
        mDecorView.setSystemUiVisibility(
                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);
    } else if (Build.VERSION.SDK_INT >= 16) {
        mDecorView.setSystemUiVisibility(
                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);
    }
    toolbar.setVisibility(View.GONE);
    layoutParams.screenBrightness = -1.00f;
    getActivity().getWindow().setAttributes(layoutParams);
    drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
    uiShowing = false;
    dimming = false;
    screenMode = 1;
}

private void hideSystemUIAndDim() {
    if (Build.VERSION.SDK_INT >= 14) {
        drawerLayout.setFitsSystemWindows(false);
    }
    getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
            | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    if (Build.VERSION.SDK_INT >= 19) {
        mDecorView.setSystemUiVisibility(
                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);
    } else if (Build.VERSION.SDK_INT >= 16) {
        mDecorView.setSystemUiVisibility(
                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);
    }
    toolbar.setVisibility(View.GONE);
    layoutParams.screenBrightness = 0.01f;
    getActivity().getWindow().setAttributes(layoutParams);
    drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
    uiShowing = false;
    dimming = true;
    screenMode = 2;
}

private void showSystemUI() {
    try {
        getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        if (Build.VERSION.SDK_INT >= 14) {
            drawerLayout.setFitsSystemWindows(true);
        }
        if (Build.VERSION.SDK_INT >= 16) {
            mDecorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        }
        toolbar.setVisibility(View.VISIBLE);
        layoutParams.screenBrightness = -1.00f;
        getActivity().getWindow().setAttributes(layoutParams);
        drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
        uiShowing = true;
        dimming = false;
        screenMode = 0;
    } catch (NullPointerException e) {
        Log.e(TAG, e.toString());
    }
}

答案 1 :(得分:1)

我以为我会在会话中添加以下代码。我需要在正常观看和全屏之间切换,并且保持各种布局困难。造成这种情况的原因是DrawerLayout处理了non-standard way中的setFitsSystemWindows()。以下代码完成了我的需要。

第一个秘密是修改setFitsSystemWindows()上的CoordinatorLayout而不是XML文件中的DrawerLayout

<android.support.v4.widget.DrawerLayout
android:id="@+id/drawerlayout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent" >

    <!-- android:fitsSystemWindows="true" moves rootCoordinatorLayout below the system status bar.
        When it is specified the theme should include <item name="android:windowTranslucentStatus">true</item>. -->
    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/coordinatorlayout"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:fitsSystemWindows="true" >

        <!-- Include other layouts specific to the app. -->

    </android.support.design.widget.CoordinatorLayout>

    <!-- The navigation drawer. -->
    <android.support.design.widget.NavigationView
        android:id="@+id/navigationview"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:layout_gravity="start"
        app:headerLayout="@layout/navigation_header"
        app:menu="@menu/navigation_menu" />
</android.support.v4.widget.DrawerLayout>

主题应在<item name="android:windowTranslucentStatus">true</item>中指定styles.xml

<resources>
    <!-- `android:windowTranslucentStatus` makes the system status bar translucent.
        When it is specified the root layout should include android:fitsSystemWindows="true". -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowTranslucentStatus">true</item>
    </style>
</resources>

在Java中,获取DrawerLayoutCoordinatorLayout的句柄。

DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawerlayout);
CoordinatorLayout coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorlayout);

此应用拥有SupportActionBar。我们需要一个处理它,以便它可以隐藏和显示。

supportActionBar = getSupportActionBar();

要将状态和导航栏切换为半透明叠加层,请使用以下代码:

if (supportActionBar.isShowing()) {  // If `supportActionBar` is visible, switch to full screen mode.
    // Hide `supportActionBar`.
    supportActionBar.hide();

    // Set `coordinatorLayout` to fit under the status and navigation bars.
    coordinatorLayout.setFitsSystemWindows(false);

    // Set the navigation bar to be translucent.
    // There is an Android Support Library bug that causes a scrim to print on the right side of the `Drawer Layout` when the navigation bar is displayed on the right of the screen.
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
} else {  // Switch to normal viewing mode.
    // Show `supportActionBar`.
    supportActionBar.show();

    // Constrain `coordinatorLayout` inside the status and navigation bars.
    coordinatorLayout.setFitsSystemWindows(true);

    // Remove the translucent navigation bar flag.
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}

或者,要在沉浸式模式下切换完全隐藏状态和导航栏,请使用以下代码。

if (supportActionBar.isShowing()) {  // If `supportActionBar` is visible, switch to full screen mode.
    // Hide `supportActionBar`.
    supportActionBar.hide();

    // Remove the translucent overlays.
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

    // Remove the translucent status bar overlay on the `Drawer Layout`, which is special and needs its own command.
    drawerLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

    /* SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
     * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
     * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically rehides them after they are shown.
     */
    coordinatorLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);

    // Set `coordinatorLayout` to fill the whole screen.
    CoordinatorLayout.setFitsSystemWindows(false);
} else {  // Switch to normal viewing mode.
    // Show `supportActionBar`.
    supportActionBar.show();

    // Add the translucent status flag if it is unset.  This also resets `drawerLayout's` `View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN`.
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

    // Remove the `SYSTEM_UI` flags from `coordinatorLayout`.
    coordinatorLayout.setSystemUiVisibility(0);

    // Constrain `coordinatorLayout` inside the status and navigation bars.
    coordinatorLayout.setFitsSystemWindows(true);
}