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.
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.
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.
Unfortunately, the problem returns when I update my phone to Android 11 (API-30). The above solution isn't effective any more. An alternate solution is @AllanVeloso's answer using app:insetForeground="@null"
And I also got a new solution. Just getting rid of SYSTEM_UI_FLAG_LAYOUT_STABLE
is it. This SYSTEM_UI_FLAG_LAYOUT_STABLE
should be the root cause of shadow effects.
For my humble research on Google Developer or StackOverflow, the flag is always explained to use with SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
and/or SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
, but there is no exact explanation about SYSTEM_UI_FLAG_LAYOUT_STABLE
itself other than:
This means that the insets seen there will always represent the worst case that the application can expect as a continuous state.
So I used it with other two automatically. But that was the root of this problem. Just removing SYSTEM_UI_FLAG_LAYOUT_STABLE
alone resolved this problem (even on Android 10 or earlier).
As you know those View.SYSTEM_UI_FLAG_*
are deprecated from Android 11 (API-30).
You will use like below:
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 {
(...)
}
As google people (like Chris Banes) explained Window.setDecorFitsSystemWindows(false)
is almost equivalent to SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
combine with SYSTEM_UI_FLAG_LAYOUT_STABLE
. There is no problem at least about shadow effects.