android - 重叠阴影效果保留在 Navigation Drawer 的 NavigationView 上

标签 android android-fullscreen navigation-drawer android-navigationview

我细化了Android Studio的Navigation Drawer Activity项目模板,使用Toolbarv7.app.ActionBarDrawerToggleNavigationView代替NavigationDrawerFragment(和 layout/fragment_navigation_drawer.xml)。

Navigation Drawer in immersive-sticky when the drawer is closed

它运行良好。然后,我更进一步。我的抽屉导航项目处于immersive-sticky(全屏)模式。

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);

    if (hasFocus) {
        View decorationView = getWindow().getDecorView();
        decorationView.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_STICKY);
    }
}

@Override
protected void onCreate(Bundle savedInstanceState) {

    ...

    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    ActionBar actionBar = getSupportActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);

    drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawerToggle = new ActionBarDrawerToggle(
            this,
            drawerLayout,
            R.string.navigation_drawer_open,  /* "open drawer" description for accessibility */
            R.string.navigation_drawer_close  /* "close drawer" description for accessibility */
    ) {
        @Override
        public void onDrawerClosed(View drawerView) {
            super.onDrawerClosed(drawerView);

            invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
        }

        @Override
        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);

            invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
        }
    };
    drawerLayout.setDrawerListener(drawerToggle);

    navigationView = (NavigationView) findViewById(R.id.navigation_view);
    navigationView.setNavigationItemSelectedListener(this);
}

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    drawerToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    drawerToggle.onConfigurationChanged(newConfig);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (drawerToggle.onOptionsItemSelected(item)) {
        return true;
    }

    ...

}

出现了一个问题。来自状态栏(顶部)和导航栏(底部)的 NavigationView 上的重叠阴影效果带保持不变。

When Navigation Drawer is opened

When Navigation Drawer is opened and sticky status and navigation bars are showed

我怎样才能摆脱它们?

我查看了 Android 的 v7.app.ActionBarDrawerToggle 或 NavigationView 的源代码,但没有成功。


更新:

感谢@lcw_gg 的建议,我已经完全摆脱了状态栏的阴影(而导航栏的阴影仍然存在)。即在layout xml中设置android:windowFullscreen属性true

但我想用 Java 代码来实现。我找到了一种方法,它可能等同于 xml 方式:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

通过这样做,您不再需要将这两个标志 - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREENView.SYSTEM_UI_FLAG_FULLSCREEN - 设置到 装饰 View .

shadow of the status bar has disappeared while that of navigation bar remains

仍然,我找不到摆脱导航栏阴影的方法。我在等待解决方案。

最佳答案

我终于成功了。

解决方案是使用 FLAG_LAYOUT_NO_LIMITSFLAG_FULLSCREENandroid.view.Window对象。

getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
        | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

这已经完美地摆脱了两个阴影。

enter image description here

lcw_gg 的评论对于操纵 android.view.Window 是非常有用的线索.特别感谢他。


Android 11 更新

不幸的是,当我将手机更新到 Android 11 (API-30) 时,问题又来了。上述解决方案不再有效。另一种解决方案是 @AllanVeloso's answer使用 app:insetForeground="@null"

而且我还得到了一个新的解决方案。 只需摆脱 SYSTEM_UI_FLAG_LAYOUT_STABLE 就可以了。这 SYSTEM_UI_FLAG_LAYOUT_STABLE 应该是阴影效果的根本原因。

对于我对 Google Developer 或 StackOverflow 的拙劣研究,该标志总是被解释为与 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 和/或 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 一起使用,但是没有确切的解释关于SYSTEM_UI_FLAG_LAYOUT_STABLE本身除了:

This means that the insets seen there will always represent the worst case that the application can expect as a continuous state.

所以我自动将它与其他两个一起使用。但这是这个问题的根源。只需单独删除 SYSTEM_UI_FLAG_LAYOUT_STABLE 即可解决此问题(即使在 Android 10 或更早版本上也是如此)。

弃用那些身临其境的 FLAG

如您所知,那些 View.SYSTEM_UI_FLAG_* 已从 Android 11 (API-30) 中弃用。

您将像下面这样使用:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    WindowInsetsController windowInsetsController = decorView.getWindowInsetsController();
    windowInsetsController.setSystemBarsBehavior(
            WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
    );
    windowInsetsController.hide(
            WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars()
    );

    window.setDecorFitsSystemWindows(false);
} else {
    (...)
}

正如谷歌人员(如 Chris Banes)所解释的,Window.setDecorFitsSystemWindows(false) 几乎等同于 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 并且 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATIONSYSTEM_UI_FLAG_LAYOUT_STABLE。至少阴影效果没有问题。

关于android - 重叠阴影效果保留在 Navigation Drawer 的 NavigationView 上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32798793/

相关文章:

android - 如何在 native react 中保存 native 日历(Android 和 iOS)的条目?

java - 如何从 JavaScriptInterface 启动抽屉导航

android - Activity 破坏 View 时如何删除 withEndAction runnable?

java - 如何为低于 28 的 API 在铃声实例上启用循环?

android - 缩放模拟器大小

android - 强制后退按钮在 Android 平板电脑上以全屏模式出现

android - 全屏 Activity 与带有通知栏和操作栏的 Activity 之间的平滑过渡

android - 在全屏和正常 Activity 之间导航

android - RadioGroup 中 RadioButtons 之间的分隔符 - 类似于 GMail 的

android - 如何在抽屉导航的主要内容 View 中使用多个 fragment