October 31, 2013, Google introduced a new version of the Android OS 4.4 KitKat, in which a lot of interesting features for developers appeared. One of these functions is
Immersive Mode . The dive mode is the mode in which your program is shown to the user on the whole screen, and any system panels, including the navigation panel (the one with the Back button) are not visible. Before Android 4.4, it was also possible to hide the system panels (
navigation bar and
status panel ). But in the existing version there was one drawback - the user could not be completely immersed in the content, since any click on the content again caused the display of system panels. The new dive mode adds another way to interact with the display of system panels. In this mode, to display the system panels to the user, it is enough to make a swipe from the top or bottom edge of the screen towards the center of the screen, while displaying the panels by clicking on the content is optional, thereby creating applications and games in which the user can fully interact with application or game with any gestures. In order for the user to understand how to call the system panels from full-screen mode, the first time the application starts, it will automatically display a system message about how to display these panels again on the screen.


You might also think that there is another problem using this mode. For example, the user has started a drawing program and wants to draw a line from the edge of the screen and how can that really cause him to display the system pane in this case? Yes, but the application will also receive messages from tapping the screen and will draw a line. By the way, now you can simply make the system panels translucent with the help of two new themes -
Theme.Holo.NoActionBar.TranslucentDecor and
Theme.Holo.Light.NoActionBar.TranslucentDecor . But it is worth remembering that in this case your content will occupy the entire area on the screen and will be visible even behind translucent system panels. If you need some part of the interface not to go outside the system panels (for example, some additional panels), you need to set the parent layout of this content to the attribute
fitsSystemWindows true. The not very pleasant thing with these themes is that it uses incomplete translucency for panels, and gradient (from black to translucent), which does not always look beautiful. If you create your own custom theme, you can follow these new themes, or manually add two new properties
windowTranslucentNavigation (whether the system navigation bar is transparent) and
windowTranslucentStatus (whether the system status panel is transparent with the clock).
')
But how to get back to full screen mode when the panels are already displayed? The user has several options - click on any content outside the system panels, wait a while for the panels to disappear automatically, or swipe from the center of the screen to the edge. The programmer can provide all these options in his application. For this, the Android team has made it so easy to implement these ways of interacting with Immersive Mode. There are two types of dive modes -
regular and
sticky . In normal mode, the programmer must decide for himself when to hide the panels, and in sticky mode, the system panels will be hidden automatically. To set both types of dive mode, you need to use the
setSystemUiVisibility () method, just pass different flags to the parameters. Call this method is necessary for the so-called Decor View, which is the appearance of the window Activity with all its design and contents. A link to this View is very easy to get.
mDecorView = getWindow().getDecorView();
Let's look at both types of dive mode in more detail.
Normal Immersive Mode
To set the normal mode, the
SYSTEM_UI_FLAG_IMMERSIVE flag is
used as a parameter to the
setSystemUiVisibility () method.
It is best to work with the usual immersive-mode to make two simple methods that will show and hide the system panels, respectively.
private void hideSystemUI() { 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_LOW_PROFILE | View.SYSTEM_UI_FLAG_IMMERSIVE); } private void showSystemUI() { mDecorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); }
For those cases when you need to show and hide the system panels by clicking on the content (
contentView ), you need to use the following code. This can be useful, for example, when watching a video, like on YouTube, where you do not need to interact with the content while watching it.
contentView.setClickable(true); final GestureDetector clickDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { boolean visible = (mDecorView.getSystemUiVisibility() & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0; if (visible) { hideSystemUI(); } else { showSystemUI(); } return true; } }); contentView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { return clickDetector.onTouchEvent(motionEvent); } });
If at the same time you have some of your own panels (
controlsView ) in your application, which also need to be hidden along with the system panels, you can also simply do this by writing the following code. Here hiding and appearance occurs using the animation of the alpha channel and the Y position of your panel.
mDecorView.setOnSystemUiVisibilityChangeListener( new View.OnSystemUiVisibilityChangeListener() { @Override public void onSystemUiVisibilityChange(int flags) { boolean visible = (flags & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0; controlsView.animate() .alpha(visible ? 1 : 0) .translationY(visible ? 0 : controlsView.getHeight()); } });
If, when launching an application, you want to show the user that the application has panels, and then hide them after a while, this is also quite simple done.
private static final int INITIAL_HIDE_DELAY = 300; @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); delayedHide(INITIAL_HIDE_DELAY); } private final Handler mHideHandler = new Handler() { @Override public void handleMessage(Message msg) { hideSystemUI(); } }; private void delayedHide(int delayMillis) { mHideHandler.removeMessages(0); mHideHandler.sendEmptyMessageDelayed(0, delayMillis); }
It may also sometimes be necessary to show the panel when the window receives focus, for example, after returning from a called dialog. This option can be processed with the following code.
@Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { delayedHide(INITIAL_HIDE_DELAY); } else { mHideHandler.removeMessages(0); } }
In this case, the panel will appear and then disappear after the time you specified.
Immersive Mode Sticky
To set the sticky mode, use the
SYSTEM_UI_FLAG_IMMERSIVE_STICKY flag as a parameter of the
setSystemUiVisibility () method.
This mode is extremely simple. If you need a situation in which the system panels will disappear when the window receives focus or it takes some time after the panels appear, then this mode is for you. To enable this mode, you need to set the window
SYSTEM_UI_FLAG_IMMERSIVE_STICKY for the window in focus. In this mode, if the window loses focus, it is automatically reset to the state it was in before the
SYSTEM_UI_FLAG_IMMERSIVE_STICKY flag was
set , that is, with all panels. As soon as the window receives focus, the panels disappear again after a while and you do not need to program this situation manually. To show the system panels, you also need, as in normal mode, to make a swipe from the edges of the screen. Turning on the stick mode is done by a simple piece of code.
@Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { 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_STICKY); } }
PS The article used
video materials
from Roman Nurik . The code of complete examples from Roman on the use of this mode can be downloaded
here .
PPS November 20, a new
article in the Training Kit on this mode. I will try to add an article in the near future, taking into account her.