Skip to content

Latest commit

 

History

History
217 lines (184 loc) · 8.43 KB

File metadata and controls

217 lines (184 loc) · 8.43 KB

Paso 03. Modo inmersivo.

En este paso vamos a ocultar las barras del sistema (la barra de estado en la parte superior y la barra de navegación en la parte inferior) aplicando el modo inmersivo. Toda esta operación se hace en la parte de Android.

Cambios en proyecto Android.

android/app/build.gradle

dependencies {
  // Dependencias estándar de Android
  ...
  implementation 'androidx.core:core:1.13.1'
  ...
}

Esto nos proporciona implementaciones compatibles con versiones anteriores de las API y funciones de la plataforma Android.

android/app/src/main/AndroidManifest.xml

Indicamos la propiedad android:inmersive="true" en la etiqueta <activity>.

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <uses-feature android:glEsVersion="0x00020000" android:required="true" />
  <application
    ...
  >
    <activity 
      ...
      android:immersive="true"
      ...
    >
      ...
    </activity>
  </application>
</manifest>

🔔 Atención.

Al añadir la propiedad android:immersive="true" no evita añadir código para el modo inmersivo, y su propósito principal es declarar que la actividad prefiere estar en modo inmersivo.

android/app/src/main/java/com/programatta/games/demoandroid/MainActivity.java

Añadimos la funcionalidad en la actividad para que las barras del sistema desaparezcan y permanezcan ocultas hasta que el usuario realice un gesto de deslizamiento. Utilizamos WindowInsetsControllerCompat para un API superior a 30 y setSystemUiVisibility() para versiones anteriores. Además, escuchamos los cambios de visibilidad para volver a aplicar los indicadores si es necesario (por ejemplo, cuando aparece el teclado).

/*
 * This source file was generated by the Gradle 'init' task
 */
package com.programatta.games.demoandroid;

import android.os.Build;
...
import android.view.View;
...
import androidx.core.view.WindowCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.core.view.WindowInsetsControllerCompat;


public class MainActivity extends AppCompatActivity {
  private static final String TAG = "DemoAndroid"; 

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ...
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // API 30+
      // Usamos WindowInsetsController para Android 11 (API 30) y superior
      hideSystemBarsApi30();
    } else {
      // Para APIs anteriores, seguiríamos usando setSystemUiVisibility()
      hideSystemBarsLegacy();
    }
    ...
  }
  ...

  private int hideSystemBars() {
    int uiOptions = 
      View.SYSTEM_UI_FLAG_LAYOUT_STABLE
    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY        // Este es el flag clave para el modo "pegajoso"
    | View.SYSTEM_UI_FLAG_FULLSCREEN
    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION         // Oculta la barra de navegación
    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; // Oculta la barra de estado
    return uiOptions;
  }

  //----------------------------------------------------------------------------------------------
  // Métodos para API 30+ (Android 11 y superior)
  //----------------------------------------------------------------------------------------------
  private void hideSystemBarsApi30() {
    // Get the WindowInsetsControllerCompat instance.
    // It handles the underlying platform API differences.
    WindowInsetsControllerCompat insetsController = WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView());
    if (insetsController == null) {
      return;
    }

    // 1. Set the behavior for how bars reappear (sticky immersive)
    insetsController.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);

    // 2. Hide the system bars using the COMPAT type
    insetsController.hide(WindowInsetsCompat.Type.systemBars());
  }

  //----------------------------------------------------------------------------------------------
  // Métodos para APIs Legacy (menos de 30)
  //----------------------------------------------------------------------------------------------
  @SuppressWarnings("deprecation") // Suprimimos la advertencia de deprecación
  private void hideSystemBarsLegacy() {
    // Establece los flags de visibilidad del sistema
    View decorView = getWindow().getDecorView();
    decorView.setSystemUiVisibility(hideSystemBars());

    // Escuchar los cambios en la visibilidad de la UI para re-aplicar los flags
    // si se pierden (ej. al aparecer el teclado).
    decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
      @Override
      public void onSystemUiVisibilityChange(int visibility) {
        if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
          // Si el flag FULLSCREEN se ha limpiado, significa que la barra
          // de estado es visible. Re-aplicamos los flags.
          decorView.setSystemUiVisibility(hideSystemBars());
        }
      }
    });
  }
}

Una vez compilado el APK e instalado en el dispositivo / emulador, podemos observar que la aplicación entra en modo inmersivo mostrando toda la pantalla y realizando un pequeño swip en la pantalla nos aparecen las barras del sistema durante un breve instante para luego desaparecer.

android inmersivo

Puedes consultar el código de este paso en la rama paso-03-01.

Splash screen.

Cuando la aplicación se levanta, durante el proceso de carga del runtime de Go y el primer rendedizado de que realiza Ebitengine la pantalla se queda en blanco. Se puede evitar esto añadiendo un splash screen en la parte de Android para que pinte la pantalla inmediatamente al arrancar.

Para ello podemos añadir una imagen y vamos a referenciarla en el tema, creando un tema nuevo para separarlo del tema de la aplicación.

  1. Añadimos una imagen (en formato png con transparecia ya que vamosa usar el color de fondo de la aplicación) en res/drawable (para la demo será la imagen de ebiten).
  2. Creamos un fichero de definición para usar la imagen y que este sea referenciado por nuestro tema en res/drawable y lo llamamos loader_background_drawable.
  3. Creamos un nuevo tema dentro de styles.xml que haga referencia a loader_background_drawable.
  4. Editamos colors.xml para añadir el nombre de color de fondo bgColorApplication y el valor a usar #CFBAF0.
  5. Aplicamos el tema en el fichero AndroidManifest.xml.
mkdir android/app/src/main/res/drawable
touch android/app/src/main/res/drawable/loader_background_drawable.xml

android/app/src/main/res/drawable/loader_background_drawable.xml.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@color/black" />
  <item>
    <bitmap
      android:src="@drawable/ebiten"
      android:gravity="center"
      android:dither="true"/>
  </item>
</layer-list>

android/app/src/main/res/values/styles.xml.

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
      <!-- Customize your theme here. -->
      ...
    </style>

    <!-- Splash theme -->
    <style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
      <item name="android:windowNoTitle">true</item>
      <item name="android:windowFullscreen">true</item>
      <item name="android:windowBackground">@drawable/loader_background_drawable</item>
    </style>
</resources>

<?xml version="1.0" encoding="utf-8"?>
<resources>
  ...
  <color name="bgColorApplication">#CFBAF0</color>
</resources>

android/app/src/main/AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <uses-feature android:glEsVersion="0x00020000" android:required="true" />
  <application
    ...
    android:theme="@style/SplashTheme">
    <activity 
      ...
    >
      ...
    </activity>
  </application>
</manifest>

Una vez compilado el APK e instalado en el dispositivo / emulador, la aplicación arranca con la imagen del splash hasta que la actividad es cargada y entra en modo inmersivo.

splash screen y modo inmersivo

Puedes consultar el código de este paso en la rama paso-03-02.