Principes de base d'Android XR : Partie 1 – Modes et panneaux spatiaux

1. Avant de commencer

Points abordés

  • Expériences utilisateur uniques qui peuvent être proposées grâce au facteur de forme XR.
  • Principes de base de l'adaptation des applications en vue de les optimiser pour les casques Android XR en utilisant les composables fournis par la bibliothèque JetPack Compose XR.
  • Utilisation des éléments d'interface utilisateur fournis par la bibliothèque Compose XR.
  • Ressources permettant d'en savoir plus sur la création d'applications pour Android XR.

Ce que cet atelier n'est pas

Ce dont vous avez besoin

Objectifs de l'atelier

Lors de cet atelier de programmation, vous améliorerez une application simple avec un seul écran afin de fournir une expérience utilisateur immersive par le biais d'Android XR.

Point de départ

Résultat final

2. Configuration

Obtenir le code

  1. Le code pour cet atelier de programmation se trouve dans le répertoire xr-fundamentals au sein du dépôt GitHub xr-codelabs. Pour cloner le dépôt, exécutez la commande suivante :
git clone https://github.com/android/xr-codelabs.git
  1. Vous pouvez aussi télécharger le dépôt sous la forme d'un fichier ZIP :

Télécharger le fichier ZIP

Ouvrir le projet

  • Après avoir démarré Android Studio, importez le projet en sélectionnant uniquement le répertoire xr-fundamentals/start. Le répertoire xr-fundamentals/part1 contient le code de solution, que vous pouvez consulter à tout moment en cas de difficulté ou pour avoir un aperçu du projet dans son ensemble.

Vous familiariser avec le code

  • Après avoir ouvert le projet dans Android Studio, prenez le temps d'examiner le code de démarrage.

3. Apprendre les concepts d'Android XR : modes et panneaux spatiaux

Lors de cet atelier de programmation, vous découvrirez deux concepts d'Android XR : les modes et les panneaux spatiaux. Vous apprendrez également comment appliquer ces concepts à une application qui s'exécute sur un appareil Android XR.

Modes

Sur les appareils Android XR, les applications s'exécutent d'un des deux modes : le mode d'affichage restreint et le mode d'affichage complet.

Mode d'affichage restreint

d779257a53898d36.jpeg

En mode d'affichage restreint, plusieurs applications s'exécutent côte à côte afin que l'utilisateur puisse effectuer des tâches en passant de l'une à l'autre. Le mode d'affichage restreint n'implique pas de devoir modifier les applications Android.

Mode d'affichage complet

c572cdee69669a23.jpeg

En mode d'affichage complet, une seule application s'exécute à la fois, sans limites spatiales. Toutes les autres applications sont masquées. Un travail supplémentaire est nécessaire pour que ces applications passent en mode d'affichage complet et utilisent les fonctionnalités additionnelles disponibles dans ce mode.

Pour en savoir plus sur ces modes, consultez la page Modes d'affichage restreint et d'affichage complet.

Panneaux spatiaux

Les panneaux spatiaux sont des éléments de conteneur qui servent de composants de base pour les applications Android XR.

Lorsque votre application s'exécute en mode d'affichage restreint, votre application sera contenue dans un panneau unique pour offrir une expérience semblable à celle d'un fenêtrage de bureau sur un appareil Android à grand écran.

Lorsqu'elle s'exécute en mode d'affichage complet, vous pouvez diviser son contenu en un ou plusieurs panneaux pour proposer une expérience plus immersive.

Pour en savoir plus, consultez la page Panneaux spatiaux.

4. Exécuter l'application dans un émulateur d'Android XR

Avant de commencer à améliorer l'application pour Android XR, vous pouvez exécuter l'application dans l'émulateur d'Android XR afin de voir à quoi elle ressemble en mode d'affichage restreint.

Installer l'image système d'Android XR

  1. Pour commencer, ouvrez SDK Manager dans Android Studio et sélectionnez l'onglet SDK Platforms (Plates-formes de SDK) si ce n'est pas déjà fait. En bas à droite de la fenêtre SDK Manager, assurez-vous que la case Show package details (Afficher les détails du package) est cochée.
  2. Dans la section Android 14, installez l'image système Android XR ARM 64 v8a ou Android XR Intel x86_64. Les images ne s'exécutent que sur les machines disposant de la même architecture (x86/ARM).

Créer un appareil Android XR virtuel

  1. Après avoir ouvert le gestionnaire d'appareils, sélectionnez XR dans la colonne Category (Catégorie) à gauche de la fenêtre. Sélectionnez ensuite le profil matériel XR Device (Appareil XR) dans la liste et cliquez sur Next (Suivant).

7a5f6b9c1766d837.png

  1. À la page suivante, sélectionnez l'image système que vous avez installée. Cliquez sur Next (Suivant), sélectionnez les options avancées de votre choix, puis créez l'AVD (appareil Android virtuel) en cliquant sur Finish (Terminer).
  2. Exécutez l'application sur l'AVD que vous venez de créer.

7cf6569ef7967d87.png

5. Configurer des dépendances

Avant de commencer à ajouter des fonctionnalités propres à XR à votre application, vous devez ajouter une dépendance à Jetpack Compose pour votre bibliothèque XR, androidx.xr.compose:compose. Celle-ci contient tous les composables dont vous avez besoin pour créer une expérience optimisée pour Android XR.

libs.version.toml

[versions]
...
xrCompose = "1.0.0-alpha01"

[libraries]
...
androidx-xr-compose = { group = "androidx.xr.compose", name = "compose", version.ref = "xrCompose" }

build.gradle.kts (Module :app)

dependencies {
    ...
    implementation(libs.androidx.xr.compose)
    ...
}

Après avoir mis à jour ces fichiers, effectuez une synchronisation Gradle afin de garantir que les dépendances sont téléchargées dans votre projet.

6. Passer en mode d'affichage complet

Pour utiliser les fonctionnalités XR comme les panneaux, votre application doit s'exécuter en mode d'affichage complet. Pour ce faire, il existe deux méthodes :

  • De façon programmatique, par exemple en réponse à une interaction de l'utilisateur dans l'application
  • Au lancement de l'application en ajoutant une directive à votre fichier manifeste

Entrer en mode d'affichage complet de façon programmatique

Pour entrer en mode d'affichage complet de façon programmatique, vous pouvez fournir des affordances à votre interface utilisateur pour permettre à l'utilisateur de choisir le mode à utiliser. En outre, vous pouvez également programmer l'entrée en mode d'affichage complet en fonction du contexte d'utilisation de l'application. Par exemple, votre application peut entrer en mode d'affichage complet lorsque l'utilisateur lance un contenu vidéo et en sortir lorsque la lecture se termine.

Pour y parvenir simplement, vous pouvez, dans un premier temps, ajouter un bouton dans la barre d'application supérieure afin d'activer ou de désactiver le mode.

  1. Créez un fichier ToggleSpaceModeButton.kt dans le package com.example.android.xrfundamentals.ui.component et ajoutez les composables suivants :

ToggleSpaceModeButton.kt

package com.example.android.xrfundamentals.ui.component

import androidx.annotation.DrawableRes
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.xr.compose.platform.LocalSpatialCapabilities
import androidx.xr.compose.platform.LocalSpatialConfiguration
import com.example.android.xrfundamentals.R
import com.example.android.xrfundamentals.ui.theme.XRFundamentalsTheme

@Composable
fun ToggleSpaceModeButton(modifier: Modifier = Modifier) {
    val spatialConfiguration = LocalSpatialConfiguration.current

    if (LocalSpatialCapabilities.current.isSpatialUiEnabled) {
        ToggleSpaceModeButton(
            modifier = modifier,
            contentDescription = "Request Home Space mode",
            iconResource = R.drawable.ic_home_space_mode,
            onClick = { spatialConfiguration.requestHomeSpaceMode() }
        )
    } else {
        ToggleSpaceModeButton(
            modifier = modifier,
            contentDescription = "Request Full Space mode",
            iconResource = R.drawable.ic_full_space_mode,
            onClick = { spatialConfiguration.requestFullSpaceMode() }
        )
    }
}

@Composable
fun ToggleSpaceModeButton(
    contentDescription: String,
    @DrawableRes iconResource: Int,
    onClick: () -> Unit,
    modifier: Modifier = Modifier
) {
    IconButton(
        modifier = modifier,
        onClick = onClick
    ) {
        Icon(
            painterResource(iconResource),
            contentDescription
        )
    }
}
  1. Ajoutez le bouton en tant qu'action dans le TopAppBar lorsque l'application s'exécute sur un appareil XR.

XRFundamentalsTopAppBar.kt

import androidx.xr.compose.platform.LocalHasXrSpatialFeature

...

TopAppBar(
    ...,
    actions = {
        // Only show the mode toggle if the device supports spatial UI
        if (LocalHasXrSpatialFeature.current) {
            ToggleSpaceModeButton()
        }
    }
)

Exécutez l'application.

L'application s'exécute en mode d'affichage restreint à son lancement. Appuyez sur le bouton en haut à droite du panneau pour passer en mode d'affichage complet.

L'application s'exécute en mode d'affichage complet. Notez que l'UI du système pour la réduction/fermeture de l'application a disparu. Appuyez sur le bouton en haut à droite du panneau pour revenir en mode d'affichage restreint.

Ces extraits de code incluent quelques nouvelles API :

  • LocalSpatialConfiguration est une composition locale qui fournit un accès à la configuration spatiale actuelle de l'application. Au-delà des méthodes permettant de changer de modes, elle inclut d'autres informations comme la taille du volume contenant l'application.
  • LocalSpatialCapabilities est une composition locale qui peut être utilisée pour déterminer quelles capacités spatiales sont actuellement disponibles pour une application. En plus du mode d'affichage (complet ou restreint), elle inclut des capacités telles que l'audio spatial et la compatibilité avec les contenus 3D.
  • LocalHasXrSpatialFeature est une composition locale qui peut être utilisée pour déterminer si une application s'exécute sur un appareil qui prend en charge les fonctionnalités d'interface utilisateur spatiale. Elle vérifie en arrière-plan si l'appareil possède la fonctionnalité système android.software.xr.immersive.

Entrer en mode d'affichage complet au démarrage

Pour demander à l'OS de lancer une activité en mode d'affichage complet, vous pouvez inclure un élément <property> avec les attributs suivants dans l'élément <activity> correspondant. Nous vous recommandons de ne le faire que s'il est peu probable que vos utilisateurs veuillent utiliser une autre application en même temps que la vôtre.

AndroidManifest.xml

<activity
    android:name=".MainActivity" 
    ... >
    <property
        android:name="android.window.PROPERTY_XR_ACTIVITY_START_MODE"
        android:value="XR_ACTIVITY_START_MODE_FULL_SPACE_MANAGED" />
</activity>

À présent, votre application se lance immédiatement en mode d'affichage complet.

abbf3d27cd2a4532.gif

Avant de continuer, supprimez l'élément <property> mentionné ci-dessus de votre fichier manifeste afin que l'application utilise le comportement par défaut, c'est-à-dire l'ouverture en mode d'affichage restreint.

7. Diviser l'interface utilisateur en plusieurs panneaux

Maintenant que votre application peut entrer en mode d'affichage complet et en sortir, il est temps de mieux exploiter cette fonctionnalité. L'une des meilleures méthodes consiste à diviser le contenu de votre application en plusieurs panneaux qui rempliront l'espace. Si vous le souhaitez, vous pouvez aussi permettre aux utilisateurs de déplacer et de redimensionner ces panneaux comme bon leur semble.

Intégrer votre application à un sous-espace

Pour commencer, ajoutez le composable Subspace après le composable Scaffold dans le composable XRFundamentalsApp. Les sous-espaces sont des partitions d'un espace 3D au sein de votre application. Vous pouvez y créer des mises en page 3D (par exemple en ajoutant des panneaux spatiaux), y placer des modèles 3D et ajouter de la profondeur à des contenus qui seraient en 2D autrement.

Lorsqu'ils sont utilisés sur un appareil non-XR, les contenus du composable Subspace n'entrent jamais dans la composition. Lorsqu'ils sont utilisés sur un appareil XR, les contenus n'entrent dans la composition que lorsque l'application s'exécute en mode d'affichage complet.

XRFundamentalsApp.kt

import androidx.xr.compose.spatial.Subspace

...

HelloAndroidXRTheme {
    Scaffold(...)
    Subspace {
    }
}

Exécutez l'application.

2d47561a616f4a11.gif

Lorsque votre application inclut un composable Subspace, celui-ci s'affichera à la place du contenu 2D. En d'autres termes, lorsque vous cliquez sur le bouton permettant d'activer le mode d'affichage complet, plus rien ne s'affiche. Pour corriger ce problème, vous devrez ajouter deux panneaux spatiaux au cours des prochaines étapes. L'un contiendra le contenu principal tandis que l'autre comportera le contenu secondaire.

Ajouter un panneau pour le contenu principal

Pour afficher le contenu principal en mode d'affichage complet, ajoutez un SpatialPanel dans le composable Subspace.

Puisqu'il s'agit du panneau principal de l'application, vous pouvez y inclure le Scaffold pour afficher les commandes dans la barre d'application supérieure. Lors du prochain atelier de programmation, vous découvrirez les orbiteurs, qui peuvent être utilisés pour spatialiser les commandes qui sont généralement disponibles dans les barres d'application, comme les commandes de navigation ou les actions contextuelles.

XRFundamentalsApp.kt

import androidx.xr.compose.subspace.SpatialPanel

...

Subspace {
    SpatialPanel() {
        Scaffold(
            topBar = { XRFundamentalsTopAppBar() }
        ) { innerPadding ->
            Box(Modifier.padding(innerPadding)) {
                PrimaryCard(
                    modifier = Modifier
                        .padding(16.dp)
                        .verticalScroll(rememberScrollState())
                )
            }
        }
    }
}

Lancez à nouveau l'application pour voir que le SpatialPanel comportant le contenu principal est désormais visible en mode d'affichage complet, mais est très petit.

89152c1991d422d4.gif

Modifier le panneau principal

Pour rendre le panneau principal plus facile à utiliser, vous pouvez l'agrandir en fournissant un SubspaceModifier. Les modificateurs de sous-espace sont semblables aux modificateurs et servent à modifier des composants spatiaux comme les panneaux.

XRFundamentalsApp.kt

import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.height
import androidx.xr.compose.subspace.layout.width
import androidx.compose.ui.unit.dp

...

SpatialPanel(
    modifier = SubspaceModifier
        .width(1024.dp)
        .height(800.dp)
){
    ...
}

Lancez à nouveau l'application. Le panneau principal devrait maintenant prendre beaucoup plus d'espace.

c4f28838e16a3eb8.gif

Ajouter un panneau pour le contenu secondaire

Maintenant que l'application fonctionne en mode d'affichage complet et que nous disposons d'un panneau pour le contenu primaire, il est temps d'offrir son propre panneau au contenu secondaire. Notez que, pour ce faire, nous utiliserons une Surface dans le panneau spatial. Sans celle-ci, les cartes secondaires n'auraient pas d'arrière-plan. En effet, les panneaux spatiaux sont transparents. À l'étape précédente, c'est le composable Scaffold qui s'est chargé de cet aspect.

XRFundamentalsApp.kt

Subspace {
    SpatialPanel() { ... }
    SpatialPanel(
        modifier = SubspaceModifier
            .width(340.dp)
            .height(800.dp)
    ) {
        Surface {
            SecondaryCardList(
                modifier = Modifier
                    .padding(16.dp)
                    .verticalScroll(rememberScrollState())
            )
        }
    }
}

Exécutez de nouveau l'application. À première vue, on pourrait croire que le second panneau ne s'affiche pas, mais en réalité, si. Il est simplement caché par le panneau principal.

7db3c3428b64e482.gif

Disposer les panneaux en ligne

Comme pour le contenu 2D, l'utilisation de lignes et de colonnes est utile pour organiser les composables côte à côte sans qu'ils ne se chevauchent. Lorsque vous travaillez avec des composants spatiaux, comme les panneaux, vous pouvez utiliser les composables SpatialRow et SpatialColumn pour y parvenir.

XRFundamentalsApp.kt

import androidx.xr.compose.subspace.SpatialRow

...

Subspace {
    SpatialRow(
        curveRadius = 825.dp
    ) {
        SpatialPanel(...) { ... }
        SpatialPanel(...) { ... }
    }
}

Lancez l'application une nouvelle fois pour voir que les panneaux sont désormais affichés en ligne, l'un à côté de l'autre. En outre, puisque nous avons fourni le curveRadius au composable SpatialRow, les panneaux se disposent autour de l'utilisateur plutôt que de rester sur le même plan, ce qui offre une expérience plus englobante.

7455811775088baf.gif

Rendre un panneau redimensionnable

Pour permettre aux utilisateurs de modifier l'apparence de votre application, vous pouvez rendre les panneaux redimensionnables en utilisant le modificateur de sous-espace resizable.

Par défaut, les panneaux redimensionnables peuvent être réduits à zéro ou développés à l'infini. Il est donc préférable de définir des paramètres minimumSize et maximumSize appropriés en fonction du contenu qu'ils vont contenir.

Consultez la documentation de référence pour en savoir plus sur les paramètres disponibles avec le modificateur resizable.

XRFundamentalsApp.kt

import androidx.xr.compose.subspace.layout.resizable

...

SpatialPanel(
    modifier = SubspaceModifier
        ...
        .resizable(true)
)

2ff2db33032fd251.gif

Rendre un panneau déplaçable

De façon similaire, vous pouvez rendre les panneaux déplaçables en utilisant le modificateur de sous-espace movable.

XRFundamentalsApp.kt

import androidx.xr.compose.subspace.layout.movable

...

SpatialPanel(
    modifier = SubspaceModifier
        ...
        .movable(true)
)

12b6166645ea1be.gif

Consultez la documentation de référence pour en savoir plus sur les paramètres disponibles avec le modificateur movable.

8. Félicitations

Pour continuer à apprendre comment exploiter Android XR au mieux, consultez les ressources et exercices ci-dessous. N'hésitez pas également à participer au bootcamp de développement Android XR.

Complément d'informations

Défis

  • Utilisez les paramètres supplémentaires disponibles pour les modificateurs de sous-espace resizable et movable.
  • Ajouter d'autres panneaux.
  • Utilisez d'autres composants spatiaux comme une boîte de dialogue spatiale.

Documents de référence