导航抽屉的NavigationView

时间:2015-09-26 15:27:53

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

我改进了Android Studio的导航抽屉活动项目模板,该模板使用工具栏 v7.app.ActionBarDrawerToggle NavigationView 代替NavigationDrawerFragment(和layout / fragment_navigation_drawer.xml)。

Navigation Drawer in immersive-sticky when the drawer is closed

完美的工作。然后,我走得更远。我的导航抽屉项目采用沉浸式粘性(全屏)模式。

@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的建议,我完全摆脱了状态栏的阴影(导航栏的阴影仍然存在)。这是在布局xml中设置android:windowFullscreen属性true

但我想在Java代码中这样做。我找到了一种方法,可能它等同于xml方式:

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

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

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

尽管如此,我还是找不到摆脱导航栏阴影的方法。我正在等待解决方案。

4 个答案:

答案 0 :(得分:16)

最后,我做到了。

解决方案是将 FLAG_LAYOUT_NO_LIMITS FLAG_FULLSCREEN 一起使用到android.view.Window对象。

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

这完全摆脱了两个阴影。

enter image description here

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

答案 1 :(得分:2)

接受答案有问题。设置标志FLAG_FULL_SCREENFLAG_LAYOUT_NO_LIMITS将使窗口的内嵌为0,并且内容可能位于系统UI的后面。

之所以会成功,是因为NavigationViewScrimInsetsFrameLayout的子类,当窗口插入全部为0时,会监听onApplyWindowInsetsView.setWillNotDraw为true。

您只需要在NavigationView中添加以下内容:

app:insetForeground="@null"

答案 2 :(得分:1)

对于那些与上述问题相同但希望始终显示系统状态栏的人(因此不使用WindowManager.LayoutParams.FLAG_FULLSCREEN),还需要做一些额外的工作来防止奇怪的内容蔓延到棒棒糖上的状态栏。当我测试它时,我没有注意到kitkat的问题。

我正在使用两个导航抽屉(左和右),奇怪的是只有左边一个投影底部的阴影。一旦应用WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,如接受的答案中所示,阴影消失,但随后状态栏下的内容蠕动以及状态栏顶部的导航抽屉绘图;一直到设备挡板。

要解决此问题,您必须在v21 styles.xml中覆盖您的主题以包含:

<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:statusBarColor">@color/colorPrimaryDark</item>

这会将内容移回状态栏下方,同时也会阻止导航抽屉在状态栏上方绘制。

除了我的v21样式中的上述条目外,我的活动代码如下所示:

// Fixes bottom navbar shadows from appearing on side navigation drawers
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    WindowManager.LayoutParams attributes = getWindow().getAttributes();
    attributes.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
    getWindow().setAttributes(attributes);
}

答案 3 :(得分:0)

感谢 hata ,我已经通过合并他的原始代码成功完全隐藏了系统UI:

@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);
  }
}

在致电onCreate之前在我的活动的inflate中添加了解决方案代码:

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

很明显,标志WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS是使我的设备(API 21)上的全屏正常工作所缺少的部分