问题
I have refined the Navigation Drawer Activity project template of Android Studio, which uses Toolbar, v7.app.ActionBarDrawerToggle and NavigationView instead of the NavigationDrawerFragment (and layout/fragment_navigation_drawer.xml).
It is perfectly working. Then, I go further. I have my Navigation Drawer project in immersive-sticky (full screen) mode.
@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;
}
...
}
A problem has risen. The bands of overlapped shadow effect on the NavigationView which are derived from status bar (on the top side) and navigation bar (on the bottom side) remain still.
How can I get rid of them?
I reviewed sources of v7.app.ActionBarDrawerToggle or NavigationView of Android, but in vain.
Updated:
Thanks for @lcw_gg's advice, I have gotten rid of the status bar's shadow completely (while the navigation bar's shadow remains). That is to set android:windowFullscreen
attribute true
in layout xml.
But I want to do this in Java code. I found a way and probably it is equivalent to the xml way:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
And with doing this, you don't need any more to set these two flags -- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
and View.SYSTEM_UI_FLAG_FULLSCREEN
-- to the decorationView
.
Still, I can't find the way to get rid of the navigation bar's shadow. I'm waiting for a solution.
回答1:
At last, I made it.
The solution is using FLAG_LAYOUT_NO_LIMITS
together with FLAG_FULLSCREEN
to the android.view.Window object.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
This has gotten rid of both of the shadows perfectly.
lcw_gg's comment was very useful clue to manipulating android.view.Window. Special thanks to him.
回答2:
The accept answer has a problem. Setting flags FLAG_FULL_SCREEN
and FLAG_LAYOUT_NO_LIMITS
will make the insets of the window to be 0 and content may lay behind the system UIs.
It will work because NavigationView
, which is a subclass of ScrimInsetsFrameLayout
, listen to onApplyWindowInsets
and View.setWillNotDraw
to true when window insets are all 0.
You just need to add to your NavigationView
this:
app:insetForeground="@null"
回答3:
For those with the same issue as above, but want to keep the system status bar always showing (thus not using WindowManager.LayoutParams.FLAG_FULLSCREEN
), there is some additional work you have to do to prevent a weird content creep underneath the status bar on lollipop. I didn't notice the issue on kitkat when I tested it.
I was using two navigation drawers (left and right) and weirdly had only the LEFT one casting the shadow on the bottom. Once applying WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
as shown in the accepted answer, the shadow went away but then had the content creep under the status bar as well as the navigation drawer drawing on top of the status bar; all the way to the device bezel.
To fix that you must overwrite your theme in v21 styles.xml to include:
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:statusBarColor">@color/colorPrimaryDark</item>
This will move the content back below the status bar and also prevent the navigation drawer from drawing on top of the status bar.
In addition to the above entries in my v21 styles, my activity code looked like this:
// 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);
}
来源:https://stackoverflow.com/questions/32798793/overlapping-shadow-effect-remains-on-navigation-drawers-navigationview