{"id":219,"date":"2015-01-18T10:55:40","date_gmt":"2015-01-18T09:55:40","guid":{"rendered":"http:\/\/www.pixnbgames.com\/blog\/?p=219"},"modified":"2015-08-21T23:52:47","modified_gmt":"2015-08-21T22:52:47","slug":"como-ocultar-los-botones-virtuales-en-android-libgdx","status":"publish","type":"post","link":"https:\/\/www.pixnbgames.com\/blog\/libgdx\/como-ocultar-los-botones-virtuales-en-android-libgdx\/","title":{"rendered":"C\u00f3mo ocultar los botones virtuales en Android \/ LibGDX"},"content":{"rendered":"<h2 style=\"text-align: justify;\">Introducci\u00f3n<\/h2>\n<p style=\"text-align: justify;\">Cuando creamos juegos para Android\u00a0con\u00a0LibGDX, normalmente querremos\u00a0que nuestra aplicaci\u00f3n ocupe toda la pantalla. Si el terminal donde ejecutamos la aplicaci\u00f3n tiene botones virtuales en pantalla para las acciones Android (Home, Back, Menu, &#8230;) en lugar de botones f\u00edsicos, veremos que nuestro juego no se ejecuta realmente a pantalla completa, ya que los botones Android permanecen en la pantalla mientras nuestro juego se ejecuta.<\/p>\n<p style=\"text-align: justify;\">Utilizando el <a title=\"Android: modo inmersivo\" href=\"https:\/\/developer.android.com\/training\/system-ui\/immersive.html\" target=\"_blank\"><strong>modo de ventana inmersivo<\/strong><\/a>, introducido en Android 4.4 KitKat (API 19),\u00a0conseguiremos ejecutar nuestro juego a pantalla completa real, ocultando\u00a0los botones virtuales de Android en caso de que existan.<\/p>\n<h2 style=\"text-align: justify;\">Usar el modo de ventana inmersivo<\/h2>\n<p style=\"text-align: justify;\">Al generar\u00a0el proyecto con LibGDX, el subproyecto Android contiene la clase <code>AndroidLauncher<\/code>, desde la que se configura c\u00f3mo se ejecutar\u00e1 nuestro juego en estos dispositivos. Por defecto, en el m\u00e9todo <code>onCreate()<\/code> se utiliza el siguiente fragmento de c\u00f3digo para mostrar la aplicaci\u00f3n a pantalla completa:<\/p>\n<pre lang=\"Java\">\/\/ Do the stuff that initialize() would do for you\r\n requestWindowFeature(Window.FEATURE_NO_TITLE);\r\n getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);\r\n getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);<\/pre>\n<p style=\"text-align: justify;\">El c\u00f3digo anterior muestra la aplicaci\u00f3n a pantalla completa, pero esto no es suficiente para ocultar los botones virtuales en caso de que existan. Para conseguirlo, hemos de utilizar el modo inmersivo de pantalla completa. De esta forma se ocultan los botones virtuales, barras de navegaci\u00f3n, etc., y volver\u00e1n a aparecer si hacemos un deslizamiento similar al que hacemos para desplegar las notificaciones. Existen dos variantes para el modo de ventana inmersivo:<\/p>\n<ul>\n<li style=\"text-align: justify;\"><code>View.SYSTEM_UI_FLAG_IMMERSIVE<\/code>: Con esta opci\u00f3n, desaparecen todos los controles, barra de navegaci\u00f3n, etc. de la pantalla. Cuando se vuelvan a mostrar, permanecer\u00e1n en la pantalla a menos que volvi\u00e9ramos a ocultarlos expl\u00edcitamente.<\/li>\n<li style=\"text-align: justify;\"><strong><code>View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY<\/code>:<\/strong> Igualmente\u00a0desaparecen todos los controles, barra de navegaci\u00f3n, etc. de la pantalla. Pero en esto caso, cuando los hacemos aparecer, se muestran de forma transl\u00facida y, pasados unos segundos, se ocultan autom\u00e1ticamente. Personalmente, esta opci\u00f3n me parece m\u00e1s recomendable para nuestros proyectos.<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">El modo de ventana inmersivo fue un cambio introducido en el API 19 (Android 4.4 KitKat), por lo que s\u00f3lo podremos usarlo a partir de esta versi\u00f3n. Si nuestro proyecto est\u00e1 configurado\u00a0para versiones anteriores de API (atributo <code>android:minSdkVersion<\/code> del archivo <em>AndroidManifest.xml<\/em>) e intentamos hacerlo, obtendremos un error. Para solucionarlo crearemos un m\u00e9todo encargado de establecer el modo inmersivo y este m\u00e9todo estar\u00e1 anotado con <code>@TargetApi(19)<\/code>, de forma que al comprobar los errores del proyecto, se tendr\u00e1 en cuenta que ese m\u00e9todo s\u00f3lo ser\u00e1 usado a partir del la versi\u00f3n 19 del API. Llamaremos a este m\u00e9todo, por ejemplo, <code>hideVirtualButtons()<\/code> y ser\u00e1 tal que as\u00ed:<\/p>\n<pre lang=\"Java\">@TargetApi(19)\r\nprivate void hideVirtualButtons() {\r\n    getWindow().getDecorView().setSystemUiVisibility(\r\n              View.SYSTEM_UI_FLAG_LAYOUT_STABLE\r\n            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION\r\n            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN\r\n            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY\r\n            | View.SYSTEM_UI_FLAG_FULLSCREEN\r\n            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);\r\n}<\/pre>\n<p style=\"text-align: justify;\">Usando\u00a0<code>@TargetApi(19)<\/code> hacemos que se tenga en cuenta en la comprobaci\u00f3n de errores, pero<strong> no impide que el c\u00f3digo se ejecute<\/strong>. Si se invoca este m\u00e9todo en un dispositivo con una versi\u00f3n de android anterior al API 19, se producir\u00e1 un error de ejecuci\u00f3n. Con el siguiente c\u00f3digo controlaremos que s\u00f3lo se utiliza en dispositivos compatibles:<\/p>\n<pre lang=\"Java\">public void onCreate() {\r\n    ....\r\n    \/\/ In KITKAT (4.4) and next releases, hide the virtual buttons\r\n    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {\r\n        hideVirtualButtons();\r\n    }\r\n}<\/pre>\n<p style=\"text-align: justify;\">Con esto, ya tendremos nuestro juego ejecut\u00e1ndose a pantalla completa real en dispositivos Android 4.4 y superiores. Sin embargo, aun queda una cuesti\u00f3n pendiente, pues si mientras estamos jugando cambiamos a otra aplicaci\u00f3n (por ejemplo, la publicidad nos abre el navegador web) y despu\u00e9s volvemos a nuestro juego, veremos que los botones virtuales vuelven a aparecer. Para corregir este comportamiento, volveremos a llamar a nuestro m\u00e9todo cada vez que nuestra aplicaci\u00f3n reciba el foco. Esto lo conseguimos sobrescribiendo el m\u00e9todo <code>onWindowsFocusChanged()<\/code> de la clase <code>AndroidLauncher<\/code>:<\/p>\n<pre lang=\"Java\">@Override\r\npublic void onWindowFocusChanged(boolean hasFocus) {\r\n\u00a0\u00a0 \u00a0super.onWindowFocusChanged(hasFocus);\r\n\u00a0\u00a0 \u00a0if (hasFocus) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\/\/ In KITKAT (4.4) and next releases, hide the virtual buttons\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0hideVirtualButtons();\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0}\r\n}<\/pre>\n<p>Ahora s\u00ed, nuestra aplicaci\u00f3n queda preparada para usar la pantalla completa.<\/p>\n<p>Para obtener m\u00e1s informaci\u00f3n puede consultar la <a title=\"Android: modo inmersivo\" href=\"https:\/\/developer.android.com\/training\/system-ui\/immersive.html\" target=\"_blank\">documentaci\u00f3n oficial<\/a>.<\/p>\n<p>Espero que este articulo le haya sido de ayuda. Muchas gracias y un saludo!<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introducci\u00f3n Cuando creamos juegos para Android\u00a0con\u00a0LibGDX, normalmente querremos\u00a0que nuestra aplicaci\u00f3n ocupe toda la pantalla. Si el terminal donde ejecutamos la aplicaci\u00f3n tiene botones virtuales en pantalla para las acciones Android (Home, Back, Menu, &#8230;) en lugar de botones f\u00edsicos, veremos <a class=\"more-link\" href=\"https:\/\/www.pixnbgames.com\/blog\/libgdx\/como-ocultar-los-botones-virtuales-en-android-libgdx\/\">Seguir leyendo <span class=\"screen-reader-text\">  C\u00f3mo ocultar los botones virtuales en Android \/ LibGDX<\/span><span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[19,14],"tags":[20,15],"language":[5],"_links":{"self":[{"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/posts\/219"}],"collection":[{"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/comments?post=219"}],"version-history":[{"count":10,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/posts\/219\/revisions"}],"predecessor-version":[{"id":838,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/posts\/219\/revisions\/838"}],"wp:attachment":[{"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/media?parent=219"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/categories?post=219"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/tags?post=219"},{"taxonomy":"language","embeddable":true,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/language?post=219"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}