How to hide virtual buttons in Android / LibGDX

When we make games with LibGDX for Android devices, we generally like our game uses full screen. If the device where we play the game has virtual buttons for Android actions (Home, Back, Menu, …) instead of physical buttons, we can see that by default our game is not showing in a truly full screen, so the virtual buttons remain on the screen while the game is playing.

Using the inmersive full screen mode, introduced in Android 4.4 KitKat (API 19), we get to run our app in a truly full screen, hiding the virtual buttons if any.

Using inmersive mode

At project generation with LibGDX, the android sub-project contains the class AndroidLauncher, where it’s configured how our game runs on android devices. By default, on the method onCreate() is used the below code in order to show the app in full screen mode:

// Do the stuff that initialize() would do for you
 requestWindowFeature(Window.FEATURE_NO_TITLE);
 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);

The previous code shows the app with full screen, but this is not enought to hide virtual buttons when them exist. To get it, we must use the inmersive full screen mode. By this way the system bar, virtual buttons, etc., will be hidden and them will be shown again when the user do a movement on the screen similar to movement used to show the notifications. There are two modes of inmersive full screen:

  • View.SYSTEM_UI_FLAG_IMMERSIVE: With this option, all buttons and the system bar are hidden. When them are shown again, they keep on the screen until we explicitly hide them.
  • View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY: Similar to previous option, this hides the system bar and virtual buttons. But in this case, when the user shows them, they are temporarily shown in a transient state and, after a few seconds, they are automatically hidden again. I prefer this options in my projects.

Inmersive full screen mode was introduced in the API level 19 (Android 4.4 kitKat), so we can only use it from this version. If our project is configured to run in previous versions (android:minSdkVersion in AndroidManifest.xml) and we try to use it, we will get an error. In order to solve it, we make a method which will be responsible of setting inmersive mode and this method will be annoted with @TargetApi(19). By this way we say to the error checking that we only want this method to use it on this version or later. We will name this method, for example, hideVirtualButtons() and  it can be like this:

@TargetApi(19)
private void hideVirtualButtons() {
    getWindow().getDecorView().setSystemUiVisibility(
              View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            | View.SYSTEM_UI_FLAG_FULLSCREEN
            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}

Using @TargetApi(19) we do that the error checking doesn’t check the method for previous versions to API level 19, but it doesn’t prevent from the code execution. If the app invoke the method in a device with an API level previous to 19, it will provoke an execution time error. With below code, we ensure the method is only executed on compatible devices:

public void onCreate() {
    ....
    // In KITKAT (4.4) and next releases, hide the virtual buttons
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        hideVirtualButtons();
    }
}

By this we already have our game running in truly full screen on devices with Android 4.4 and later. However, there is still a pending issue, because if while the user is playing our game, he goes to another app (for example, he goes to web browser by clicking an ad) and then return to our game, virtual buttons appear and remain on the screen. To correct this, we will invoke our method again every time our app gets the focus. We do it by overriding the method onWindowsFocusChanged(), on class AndroidLauncher:

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {
        // In KITKAT (4.4) and next releases, hide the virtual buttons
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            hideVirtualButtons();
        }
    }
}

Now yes!, our app is ready to use truly full screen.

To get more information you can go to the official documentation.

I hope this post is useful for you. Many thanks and regards!

 

3 comentarios en «How to hide virtual buttons in Android / LibGDX»

    • Hi @breakmt,

      Maybe for a single android version, some flags are redundant. But this flags combination is the way that I have found to get the desired behavior for every Android versions.

      Thanks for comment and kind regards

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*