1. Introduction
Les grands écrans vous permettent de créer des mises en page et des interfaces utilisateur qui améliorent l'expérience utilisateur et augmentent la productivité. Toutefois, si votre application est conçue pour les petits écrans des téléphones non pliables, elle ne peut probablement pas profiter de l'espace supplémentaire disponible sur les tablettes, les pliables et les appareils ChromeOS.
Mettre à jour une application pour tirer le meilleur parti possible des grands écrans peut prendre beaucoup de temps et s'avérer coûteux, en particulier pour les anciennes applications basées sur plusieurs activités.
L'intégration d'activités, introduite dans Android 12L (niveau d'API 32), permet aux applications basées sur des activités d'afficher plusieurs activités simultanément sur les grands écrans en créant une mise en page à deux volets (Liste/Détail, par exemple). Aucune modification du code Kotlin ou Java n'est nécessaire. Il vous suffit d'ajouter des dépendances, de créer un fichier de configuration XML, d'implémenter un initialiseur et d'ajouter quelques éléments au fichier manifeste de l'application. Si vous préférez manipuler du code, vous pouvez ajouter simplement quelques appels d'API Jetpack WindowManager à la méthode onCreate()
de l'activité principale de votre application.
Conditions préalables
Voici les conditions à réunir pour effectuer cet atelier de programmation :
- Vous savez créer des applications Android.
- Vous connaissez le fonctionnement des activités.
- Vous connaissez le langage XML.
- Vous connaissez Android Studio, y compris la configuration d'appareils virtuels.
Objectifs de l'atelier
Dans cet atelier de programmation, vous allez mettre à jour une application basée sur des activités afin de permettre une mise en page à deux volets semblable à SlidingPaneLayout
. Sur les petits écrans, l'application superpose les activités (piles) les unes sur les autres dans la fenêtre de tâches.
Sur les grands écrans, l'application affiche deux activités simultanément à l'écran, côte à côte ou en haut et en bas, en fonction de vos spécifications.
Points abordés
Implémenter l'intégration d'activités de deux façons :
- Avec un fichier de configuration XML
- Avec des appels d'API Jetpack WindowManager
Ce dont vous avez besoin
- Version récente d'Android Studio
- Téléphone ou émulateur Android
- Petite tablette ou émulateur Android
- Grande tablette ou émulateur Android
2. Configuration
Obtenir l'application exemple
Étape 1 : Cloner le dépôt
Clonez le dépôt Git pour les ateliers de programmation spécifiques aux grands écrans :
git clone https://github.com/android/large-screen-codelabs
Vous pouvez aussi télécharger et décompresser le fichier ZIP correspondant aux ateliers de programmation pour les grands écrans :
Étape 2 : Inspecter les fichiers sources de l'atelier de programmation
Accédez au dossier activity-embedding
:
Étape 3 : Ouvrir le projet de l'atelier de programmation
Dans Android Studio, ouvrez le projet Kotlin ou Java.
Le dossier activity-embedding
du dépôt et du fichier ZIP contient deux projets Android Studio : un en Kotlin et un en Java. Ouvrez le projet de votre choix. Les extraits de code sont fournis dans les deux langages.
Créer des appareils virtuels
Si vous ne disposez pas d'un téléphone Android, d'une petite tablette ou d'une grande tablette avec un niveau d'API 32 ou supérieur, ouvrez le gestionnaire d'appareils dans Android Studio et créez les appareils virtuels suivants dont vous avez besoin parmi ceux ci-dessous :
- Téléphone : Pixel 6, niveau d'API 32 ou supérieur
- Petite tablette : 7 WSVGA (tablette), niveau d'API 32 ou supérieur
- Grande tablette : Pixel C, niveau d'API 32 ou supérieur
3. Exécuter l'application
L'application exemple affiche une liste d'éléments. Lorsque l'utilisateur sélectionne un de ces éléments, l'application affiche des informations le concernant.
L'application comporte trois activités :
ListActivity
: contient une liste d'éléments dans uneRecyclerView
.DetailActivity
: affiche les informations sur l'élément sélectionné dans la liste.SummaryActivity
: affiche un résumé des informations lorsque l'élément "Summary" (Résumé) est sélectionné dans la liste.
Comportement sans l'intégration d'activités
Exécutez l'application exemple pour voir son comportement sans l'intégration d'activités :
- Exécutez l'application exemple sur votre grande tablette ou votre émulateur Pixel C. L'activité principale (à savoir, la liste) s'affiche :
- Sélectionnez un élément de la liste pour lancer une activité secondaire (à savoir, le détail de l'élément sélectionné). L'activité "Détail" se superpose à l'activité "Liste" :
- Faites pivoter la tablette en mode paysage. L'activité secondaire est toujours superposée à l'activité principale et occupe la totalité de l'écran :
- Sélectionnez la commande "Retour" (flèche vers la gauche dans la barre d'application) pour revenir à la liste.
- Sélectionnez le dernier élément de la liste, "Summary" (Résumé) pour lancer une activité récapitulative en tant qu'activité secondaire. Cette activité se superpose à l'activité "Liste" :
- Faites pivoter la tablette en mode paysage. L'activité secondaire est toujours superposée à l'activité principale et occupe la totalité de l'écran :
Comportement avec l'intégration d'activités
Une fois cet atelier de programmation terminé, l'orientation paysage affiche les activités "Liste" et "Détail" côte à côte dans une mise en page de type "Liste/Détail" :
Toutefois, vous allez configurer le résumé pour qu'il s'affiche en plein écran, même si l'activité est lancée depuis un écran fractionné. Le résumé se superpose à l'écran fractionné :
4. Contexte
L'intégration d'activités divise la fenêtre de tâches de l'application en deux conteneurs : un conteneur principal et un conteneur secondaire. Toute activité peut générer un fractionnement en lançant une autre activité. L'activité initiale occupe alors le conteneur principal, et l'activité lancée le conteneur secondaire.
L'activité principale peut lancer des activités supplémentaires dans le conteneur secondaire. Les activités des deux conteneurs peuvent ensuite lancer des activités dans leurs conteneurs respectifs. Chaque conteneur peut comporter une pile d'activités. Pour en savoir plus, consultez le guide du développeur sur l'intégration d'activités.
Vous allez configurer votre application pour qu'elle accepte l'intégration d'activités en créant un fichier de configuration XML ou en effectuant des appels d'API Jetpack WindowManager. Commençons par l'approche de configuration XML.
5. Configuration XML
Les conteneurs et les fractionnements liés à l'intégration d'activités sont créés et gérés par la bibliothèque Jetpack WindowManager. Ils reposent sur des règles de fractionnement que vous créez dans un fichier de configuration XML.
Ajouter la dépendance WindowManager
Autorisez l'application exemple à accéder à la bibliothèque WindowManager en ajoutant la dépendance de la bibliothèque au fichier build.gradle
au niveau du module de l'application. Exemple :
build.gradle
implementation 'androidx.window:window:1.2.0'
Informer le système
Indiquez au système que votre application a implémenté l'intégration d'activités.
Ajoutez la propriété android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED
à l'élément <application>
du fichier manifeste de l'application, puis définissez sa valeur sur "true" :
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<property
android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED"
android:value="true" />
</application>
</manifest>
Ce paramètre permet aux fabricants d'appareils (OEM) d'activer des fonctionnalités personnalisées pour les applications compatibles avec l'intégration d'activités. Par exemple, les appareils peuvent utiliser le format letterbox pour une activité en mode portrait sur les affichages en mode paysage (voir android:screenOrientation
). L'activité sera ainsi orientée de sorte à passer à une mise en page à deux volets :
Créer un fichier de configuration
Créez un fichier de ressources XML nommé main_split_config.xml
dans le dossier res/xml
de votre application avec l'élément racine resources
.
Remplacez l'espace de noms XML par :
main_split_config.xml
xmlns:window="http://schemas.android.com/apk/res-auto"
Règle de paire de fractionnement
Ajoutez la règle de fractionnement suivante au fichier de configuration :
main_split_config.xml
<!-- Define a split for the named activity pair. -->
<SplitPairRule
window:splitRatio="0.33"
window:splitMinWidthDp="840"
window:finishPrimaryWithSecondary="never"
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".ListActivity"
window:secondaryActivityName=".DetailActivity"/>
</SplitPairRule>
Cette règle a l'effet suivant :
- Configure les options de fractionnement pour les activités qui partagent un écran :
splitRatio
: indique la partie de la fenêtre de tâches occupée par l'activité principale (33 %), ce qui laisse l'espace restant à l'activité secondaire.splitMinWidthDp
: spécifie la largeur minimale (840) requise pour que les deux activités s'affichent simultanément à l'écran. Les unités sont des pixels indépendants de l'affichage (dp).
finishPrimaryWithSecondary
: spécifie si les activités du conteneur fractionné principal se terminent (ou ne se terminent jamais) lorsque toutes les activités du conteneur secondaire sont finalisées.finishSecondaryWithPrimary
: spécifie si les activités du conteneur fractionné secondaire se terminent (toujours) lorsque toutes les activités de l'activité du conteneur principal sont finalisées.- Inclut un filtre de fractionnement qui définit les activités qui partagent un fractionnement de fenêtre de tâches. L'activité principale est
ListActivity
.DetailActivity
est l'activité secondaire.
Règle d'espace réservé
Une activité d'espace réservé occupe le conteneur secondaire d'un fractionnement d'activité lorsqu'aucun contenu n'est disponible pour ce conteneur spécifique, par exemple lorsqu'un fractionnement liste/détails s'ouvre, mais qu'aucun élément n'a encore été sélectionné dans la liste. Pour en savoir plus, consultez la section Espaces réservés dans le guide du développeur sur l'intégration d'activités.
Ajoutez la règle d'espace réservé suivante au fichier de configuration :
main_split_config.xml
<!-- Automatically launch a placeholder for the detail activity. -->
<SplitPlaceholderRule
window:placeholderActivityName=".PlaceholderActivity"
window:splitRatio="0.33"
window:splitMinWidthDp="840"
window:finishPrimaryWithPlaceholder="always"
window:stickyPlaceholder="false">
<ActivityFilter
window:activityName=".ListActivity"/>
</SplitPlaceholderRule>
Cette règle a l'effet suivant :
- Identifie l'activité d'espace réservé,
PlaceholderActivity
(nous la créerons à l'étape suivante). - Configure les options de l'espace réservé :
splitRatio
: indique la partie de la fenêtre de tâches occupée par l'activité principale (33 %), ce qui laisse l'espace restant à l'espace réservé. En règle générale, cette valeur doit correspondre au ratio de fractionnement de la règle de paire de fractionnement à laquelle l'espace réservé est associé.splitMinWidthDp
: spécifie la largeur minimale (840) requise pour que l'espace réservé s'affiche à l'écran avec l'activité principale. En règle générale, cette valeur doit correspondre à la largeur minimale de la règle de paire de fractionnement à laquelle l'espace réservé est associé. Les unités sont des pixels indépendants de l'affichage (dp).finishPrimaryWithPlaceholder
: indique si les activités du conteneur fractionné principal se terminent (toujours) lorsque l'espace réservé prend fin.stickyPlaceholder
: indique si l'espace réservé doit rester à l'écran (false) comme activité supérieure lorsque l'écran est redimensionné pour afficher deux volets, par exemple lorsqu'un appareil pliable est plié.- Inclut un filtre d'activité qui spécifie l'activité (
ListActivity
) avec laquelle l'espace réservé partage un fractionnement de la fenêtre de tâches.
L'espace réservé remplace l'activité secondaire de la règle de paire de fractionnement dont l'activité principale est identique à celle du filtre d'activité de l'espace réservé (voir "Règle de paire de fractionnement" dans la section "Configuration XML" de cet atelier de programmation).
Règle d'activité
Les règles d'activité sont des règles générales. Vous pouvez les spécifier pour les activités dont vous souhaitez qu'elles occupent l'intégralité de la fenêtre de tâches, à savoir pour les activités qui ne font jamais l'objet d'un fractionnement. Pour en savoir plus, consultez l'article Fenêtre modale plein écran du guide du développeur sur l'intégration d'activités.
Nous allons maintenant faire en sorte que l'activité récapitulative occupe l'intégralité de la fenêtre de tâches en la superposant à l'écran fractionné. Pour revenir au fractionnement, il suffira d'utiliser la navigation arrière.
Ajoutez la règle d'activité suivante au fichier de configuration :
main_split_config.xml
<!-- Activities that should never be in a split. -->
<ActivityRule
window:alwaysExpand="true">
<ActivityFilter
window:activityName=".SummaryActivity"/>
</ActivityRule>
Cette règle a l'effet suivant :
- Identifie l'activité qui doit s'afficher en plein écran (
SummaryActivity).
). - Configure les options de l'activité :
alwaysExpand
: indique si l'activité doit se développer pour occuper tout l'espace d'affichage disponible.
Fichier source
Une fois terminé, votre fichier de configuration XML devrait se présenter comme suit :
main_split_config.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:window="http://schemas.android.com/apk/res-auto">
<!-- Define a split for the named activity pair. -->
<SplitPairRule
window:splitRatio="0.33"
window:splitMinWidthDp="840"
window:finishPrimaryWithSecondary="never"
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".ListActivity"
window:secondaryActivityName=".DetailActivity"/>
</SplitPairRule>
<!-- Automatically launch a placeholder for the detail activity. -->
<SplitPlaceholderRule
window:placeholderActivityName=".PlaceholderActivity"
window:splitRatio="0.33"
window:splitMinWidthDp="840"
window:finishPrimaryWithPlaceholder="always"
window:stickyPlaceholder="false">
<ActivityFilter
window:activityName=".ListActivity"/>
</SplitPlaceholderRule>
<!-- Activities that should never be in a split. -->
<ActivityRule
window:alwaysExpand="true">
<ActivityFilter
window:activityName=".SummaryActivity"/>
</ActivityRule>
</resources>
Créer une activité d'espace réservé
Vous devez créer une activité qui servira d'espace réservé spécifié dans le fichier de configuration XML. Cette activité peut être très simple et indiquer, par exemple, aux utilisateurs que le contenu finira par s'afficher ici.
Créez l'activité dans le dossier source principal de l'application exemple.
Dans Android Studio, procédez comme suit :
- Effectuez un clic droit sur le dossier source de l'application exemple,
com.example.activity_embedding
. - Sélectionnez New > Activity > Empty Views Activity (Nouveau > Activité > Vues vides).
- Nommez l'activité PlaceholderActivity.
- Sélectionnez Finish (Terminer).
Android Studio crée alors l'activité dans le package de l'application exemple, l'ajoute au fichier manifeste de l'application et génère un fichier de ressources de mise en page nommé activity_placeholder.xm
l dans le dossier res/layout
.
- Dans le fichier
AndroidManifest.xml
de l'application exemple, définissez le libellé de l'activité d'espace réservé sur une chaîne vide :
AndroidManifest.xml
<activity
android:name=".PlaceholderActivity"
android:exported="false"
android:label="" />
- Remplacez le contenu du fichier de mise en page
activity_placeholder.xml
dans le dossierres/layout
par le code suivant :
activity_placeholder.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:background="@color/gray"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".PlaceholderActivity">
<TextView
android:id="@+id/textViewPlaceholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/placeholder_text"
android:textSize="36sp"
android:textColor="@color/obsidian"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
- Enfin, ajoutez la ressource de chaîne suivante au fichier de ressources
strings.xml
dans le dossierres/values
:
strings.xml
<string name="placeholder_text">Placeholder</string>
Créer un initialiseur
Le composant RuleController
de WindowManager analyse les règles définies dans le fichier de configuration XML, puis les met à disposition du système.
Un initialiseur de la bibliothèque Jetpack Startup permet à RuleController
d'accéder au fichier de configuration.
La bibliothèque Startup effectue l'initialisation des composants au démarrage de l'application. L'initialisation doit être effectuée avant le début des activités pour que RuleController
ait accès aux règles de fractionnement et puisse les appliquer si nécessaire.
Ajouter la dépendance de la bibliothèque Startup
Pour activer la fonctionnalité de démarrage, ajoutez la dépendance de la bibliothèque Startup au fichier build.gradle
de l'application exemple au niveau du module, par exemple :
build.gradle
implementation 'androidx.startup:startup-runtime:1.1.1'
Implémenter un initialiseur pour RuleController
Créez une implémentation de l'interface Startup Initializer.
Dans Android Studio, procédez comme suit :
- Effectuez un clic droit sur le dossier source de l'application exemple,
com.example.activity_embedding
. - Sélectionnez New > Kotlin Class/File (Nouveau > Classe/Fichier Kotlin) ou New > Java Class (Nouveau > Classe Java).
- Nommez la classe SplitInitializer.
- Appuyez sur Entrée : Android Studio crée la classe dans le package de l'application exemple.
- Remplacez le contenu du fichier de classe par le suivant :
SplitInitializer.kt
package com.example.activity_embedding
import android.content.Context
import androidx.startup.Initializer
import androidx.window.embedding.RuleController
class SplitInitializer : Initializer<RuleController> {
override fun create(context: Context): RuleController {
return RuleController.getInstance(context).apply {
setRules(RuleController.parseRules(context, R.xml.main_split_config))
}
}
override fun dependencies(): List<Class<out Initializer<*>>> {
return emptyList()
}
}
SplitInitializer.java
package com.example.activity_embedding;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.startup.Initializer;
import androidx.window.embedding.RuleController;
import java.util.Collections;
import java.util.List;
public class SplitInitializer implements Initializer<RuleController> {
@NonNull
@Override
public RuleController create(@NonNull Context context) {
RuleController ruleController = RuleController.getInstance(context);
ruleController.setRules(
RuleController.parseRules(context, R.xml.main_split_config)
);
return ruleController;
}
@NonNull
@Override
public List<Class<? extends Initializer<?>>> dependencies() {
return Collections.emptyList();
}
}
L'initialiseur met les règles de fractionnement à disposition du composant RuleController
en transmettant l'ID du fichier de ressources XML contenant les définitions (main_split_config
) à la méthode parseRules()
du composant. La méthode setRules()
ajoute les règles analysées à RuleController
.
Créer un fournisseur d'initialisation
Un fournisseur appelle le processus d'initialisation des règles de fractionnement.
Ajoutez androidx.startup.InitializationProvider
à l'élément <application>
du fichier manifeste de l'application exemple en tant que fournisseur, puis référencez SplitInitializer
:
AndroidManifest.xml
<provider android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<!-- Make SplitInitializer discoverable by InitializationProvider. -->
<meta-data android:name="${applicationId}.SplitInitializer"
android:value="androidx.startup" />
</provider>
InitializationProvider
initialise SplitInitializer
, qui appelle à son tour les méthodes RuleController
qui analysent le fichier de configuration XML (main_split_config.xml
) et ajoutent les règles à RuleController
(voir "Implémenter un initialiseur pour RuleController" ci-dessus).
InitializationProvider
détecte et initialise SplitInitializer
avant l'exécution de la méthode onCreate()
de l'application. Les règles de fractionnement sont donc appliquées lorsque l'activité principale de l'application commence.
Fichier source
Voici le fichier manifeste final de l'application :
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Activity_Embedding"
tools:targetApi="32">
<activity
android:name=".ListActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".DetailActivity"
android:exported="false"
android:label="" />
<activity
android:name=".SummaryActivity"
android:exported="false"
android:label="" />
<activity
android:name=".PlaceholderActivity"
android:exported="false"
android:label="" />
<property
android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED"
android:value="true" />
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<!-- Make SplitInitializer discoverable by InitializationProvider. -->
<meta-data
android:name="${applicationId}.SplitInitializer"
android:value="androidx.startup" />
</provider>
</application>
</manifest>
Raccourci d'initialisation
Si vous savez comment combiner des configurations XML avec les API WindowManager, vous pouvez supprimer l'initialiseur de la bibliothèque Startup et le fournisseur du fichier manifeste afin de simplifier l'implémentation.
Une fois le fichier de configuration XML créé, procédez comme suit :
Étape 1 : Créer une sous-classe de Application
Votre sous-classe d'application sera la première classe instanciée lors de la création du processus de votre application. Ajoutez les règles de fractionnement à RuleController
dans la méthode onCreate()
de votre sous-classe pour vous assurer qu'elles entrent en vigueur avant le lancement des activités.
Dans Android Studio, procédez comme suit :
- Effectuez un clic droit sur le dossier source de l'application exemple,
com.example.activity_embedding
. - Sélectionnez New > Kotlin Class/File (Nouveau > Classe/Fichier Kotlin) ou New > Java Class (Nouveau > Classe Java).
- Nommez cette classe SampleApplication.
- Appuyez sur Entrée : Android Studio crée la classe dans le package de l'application exemple.
- Étendez la classe à partir du supertype
Application
.
SampleApplication.kt
package com.example.activity_embedding
import android.app.Application
/**
* Initializer for activity embedding split rules.
*/
class SampleApplication : Application() {
}
SampleApplication.java
package com.example.activity_embedding;
import android.app.Application;
/**
* Initializer for activity embedding split rules.
*/
public class SampleApplication extends Application {
}
Étape 2 : Initialiser RuleController
Ajoutez les règles de fractionnement du fichier de configuration XML à RuleController
dans la méthode onCreate()
de la sous-classe d'application.
Pour ajouter les règles à RuleController
, procédez comme suit :
- Obtenez une instance singleton de
RuleController
. - Utilisez la méthode
RuleController
associée Java statique ou Kotlin deparseRules()
pour analyser le fichier XML. - Ajoutez les règles analysées à
RuleController
avec la méthodesetRules()
.
SampleApplication.kt
override fun onCreate() {
super.onCreate()
RuleController.getInstance(this)
.setRules(RuleController.parseRules(this, R.xml.main_split_config))
}
SampleApplication.java
@Override
public void onCreate() {
super.onCreate();
RuleController.getInstance(this)
.setRules(RuleController.parseRules(this, R.xml.main_split_config));
}
Étape 3 : Ajouter le nom de votre sous-classe au fichier manifeste
Ajoutez le nom de votre sous-classe à l'élément <application>
du fichier manifeste de l'application :
AndroidManifest.xml
<application
android:name=".SampleApplication"
. . .
Exécuter le code
Créer et exécuter l'application exemple
Sur un téléphone non pliable, les activités sont toujours empilées, même en mode paysage :
Sur Android 13 (niveau d'API 33) ou version antérieure, l'intégration d'activités n'est pas activée sur les téléphones non pliables, quelle que soit la largeur minimale de fractionnement.
La prise en charge de l'intégration d'activités pour les téléphones non pliables à des niveaux d'API plus élevés varie selon que le fabricant de l'appareil l'a activée.
Sur une petite tablette ou dans l'émulateur WSVGA 7 (tablette), les deux activités sont empilées en mode portrait, mais apparaissent côte à côte en mode paysage :
Sur une grande tablette ou dans l'émulateur Pixel C, les activités sont empilées en mode portrait (voir "Format" ci-dessous), mais s'affichent côte à côte en mode paysage :
Le résumé s'affiche en plein écran en mode paysage même s'il a été lancé depuis un écran fractionné :
Format
Les fractionnements d'activité sont contrôlés par le format d'affichage en plus de la largeur minimale de fractionnement. Les attributs splitMaxAspectRatioInPortrait
et splitMaxAspectRatioInLandscape
spécifient le format maximal (height:width) pour lequel les fractionnements d'activité sont affichés. Les attributs représentent les propriétés maxAspectRatioInPortrait
et maxAspectRatioInLandscape
de SplitRule
.
Si le format d'un écran dépasse cette valeur dans les deux sens, les écrans fractionnés sont désactivés, quelle que soit la largeur de l'écran. La valeur par défaut pour l'orientation portrait est de 1,4 (voir SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT
), ce qui empêche les longs écrans étroits d'inclure les écrans fractionnés. Par défaut, les fractionnements sont toujours autorisés en mode paysage (voir SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT
).
La largeur d'affichage en mode portrait de l'émulateur Pixel C est de 900 dp, ce qui est plus large que le paramètre splitMinWidthDp
dans le fichier de configuration XML de l'application exemple. L'émulateur devrait donc afficher un fractionnement d'activité. Toutefois, le format de la Pixel C en mode portrait est supérieur à 1,4, ce qui empêche les fractionnements d'activités de s'afficher en mode portrait.
Vous pouvez définir le format maximal pour les affichages portrait et paysage dans les éléments SplitPairRule
et SplitPlaceholderRule
du fichier de configuration XML. Par exemple :
main_split_config.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:window="http://schemas.android.com/apk/res/android">
<!-- Define a split for the named activity pair. -->
<SplitPairRule
. . .
window:splitMaxAspectRatioInPortrait="alwaysAllow"
window:splitMaxAspectRatioInLandscape="alwaysDisallow"
. . .
</SplitPairRule>
<SplitPlaceholderRule
. . .
window:splitMaxAspectRatioInPortrait="alwaysAllow"
window:splitMaxAspectRatioInLandscape="alwaysDisallow"
. . .
</SplitPlaceholderRule>
</resources>
Sur une grande tablette dont la largeur d'écran en mode portrait est supérieure ou égale à 840 dp, ou avec l'émulateur Pixel C, les activités sont côte à côte en mode portrait, mais empilées en mode paysage :
Bonus
Essayez de définir le format dans l'application exemple, comme indiqué ci-dessus pour les orientations portrait et paysage. Testez les paramètres avec votre grande tablette (si la largeur du portrait est d'au moins 840 dp) ou avec l'émulateur Pixel C. Vous devriez voir un fractionnement d'activité en mode portrait, mais pas en mode paysage.
Déterminez le format portrait de votre grande tablette (celui de la Pixel C est légèrement supérieur à 1,4). Définissez des valeurs supérieures et inférieures au format pour splitMaxAspectRatioInPortrait
. Exécutez l'application et observez les résultats.
6. API WindowManager
Vous pouvez activer l'intégration d'activités dans le code avec une seule méthode appelée depuis la méthode onCreate()
de l'activité qui lance le fractionnement. Si vous préférez utiliser du code plutôt que XML, il s'agit de la marche à suivre.
Ajouter la dépendance WindowManager
Que vous créiez une implémentation XML ou que vous utilisiez des appels d'API, votre application doit avoir accès à la bibliothèque WindowManager. Consultez la section "Configuration XML" de cet atelier de programmation pour découvrir comment ajouter la dépendance WindowManager à votre application.
Informer le système
Que vous utilisiez un fichier de configuration XML ou des appels d'API WindowManager, votre application doit avertir le système qu'elle a implémenté l'intégration d'activités. Consultez la section "Configuration XML" de cet atelier de programmation pour découvrir comment informer le système de votre implémentation.
Créer une classe pour gérer les fractionnements
Dans cette section de l'atelier de programmation, vous allez entièrement implémenter un fractionnement d'activité dans une seule méthode d'objet statique ou associée que vous appellerez à partir de l'activité principale de l'application exemple, ListActivity
.
Créez une classe nommée SplitManager
avec une méthode nommée createSplit
qui inclut un paramètre context
(certains appels d'API nécessitent ce paramètre) :
SplitManager.kt
class SplitManager {
companion object {
fun createSplit(context: Context) {
}
}
SplitManager.java
class SplitManager {
static void createSplit(Context context) {
}
}
Appelez cette méthode dans la méthode onCreate()
d'une sous-classe de la classe Application
.
Pour découvrir pourquoi et comment sous-classer Application
, consultez "Raccourci d'initialisation" dans la section "Configuration XML" de cet atelier de programmation.
SampleApplication.kt
package com.example.activity_embedding
import android.app.Application
/**
* Initializer for activity embedding split rules.
*/
class SampleApplication : Application() {
override fun onCreate() {
super.onCreate()
SplitManager.createSplit(this)
}
}
SampleApplication.java
package com.example.activity_embedding;
import android.app.Application;
/**
* Initializer for activity embedding split rules.
*/
public class SampleApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
SplitManager.createSplit(this);
}
}
Créer une règle de fractionnement
API requises :
SplitPairRule
définit une règle de fractionnement pour une paire d'activités.
SplitPairRule.Builder
crée une SplitPairRule
. Le compilateur utilise un ensemble d'objets SplitPairFilter
comme argument. Les filtres spécifient quand appliquer la règle.
Vous devez enregistrer la règle avec une instance singleton du composant RuleController
, ce qui met les règles de fractionnement à disposition du système.
Pour créer une règle de fractionnement, procédez comme suit :
- Créez un filtre de paire de fractionnement qui identifie
ListActivity
etDetailActivity
comme les activités qui partagent un fractionnement :
SplitManager.kt/createSplit()
val splitPairFilter = SplitPairFilter(
ComponentName(context, ListActivity::class.java),
ComponentName(context, DetailActivity::class.java),
null
)
SplitManager.java/createSplit()
SplitPairFilter splitPairFilter = new SplitPairFilter(
new ComponentName(context, ListActivity.class),
new ComponentName(context, DetailActivity.class),
null
);
Le filtre peut inclure une action d'intent (troisième paramètre) pour le lancement de l'activité secondaire. Si vous incluez une action d'intent, le filtre la recherche avec le nom de l'activité. Pour les activités de votre propre application, vous ne filtrerez probablement pas les actions d'intent. L'argument peut donc être nul.
- Ajoutez le filtre à un ensemble de filtres :
SplitManager.kt/createSplit()
val filterSet = setOf(splitPairFilter)
SplitManager.java/createSplit()
Set<SplitPairFilter> filterSet = new HashSet<>();
filterSet.add(splitPairFilter);
- Créez des attributs de mise en page pour le fractionnement :
SplitManager.kt/createSplit()
val splitAttributes: SplitAttributes = SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.ratio(0.33f))
.setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
.build()
SplitManager.java/createSplit()
SplitAttributes splitAttributes = new SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.ratio(0.33f))
.setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
.build();
SplitAttributes.Builder
crée un objet contenant des attributs de mise en page :
setSplitType
: définit la manière dont la zone d'affichage disponible est allouée à chaque conteneur d'activité. Le type de fractionnement des proportions spécifie la proportion de l'écran occupé par le conteneur principal. Le conteneur secondaire occupe le reste de la zone d'affichage.setLayoutDirection
: spécifie la disposition des conteneurs d'activités les uns par rapport aux autres (le conteneur principal en premier).
- Créez une règle de paire de fractionnement :
SplitManager.kt/createSplit()
val splitPairRule = SplitPairRule.Builder(filterSet)
.setDefaultSplitAttributes(splitAttributes)
.setMinWidthDp(840)
.setMinSmallestWidthDp(600)
.setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
.setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
.setClearTop(false)
.build()
SplitManager.java/createSplit()
SplitPairRule splitPairRule = new SplitPairRule.Builder(filterSet)
.setDefaultSplitAttributes(splitAttributes)
.setMinWidthDp(840)
.setMinSmallestWidthDp(600)
.setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
.setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
.setClearTop(false)
.build();
SplitPairRule.Builder
crée et configure la règle :
filterSet
: contient des filtres de paire de fractionnement qui déterminent quand appliquer la règle en identifiant les activités qui partagent un fractionnement. Dans l'application exemple,ListActivity
etDetailActivity
sont spécifiés dans un filtre de paire de fractionnement (voir les étapes précédentes).setDefaultSplitAttributes
: applique des attributs de mise en page à la règle.setMinWidthDp
: définit la largeur d'affichage minimale (en pixels indépendants de la densité, dp) pour permettre le fractionnement.setMinSmallestWidthDp
: définit la valeur minimale (en dp) que la plus petite des deux dimensions d'affichage doit avoir pour permettre un fractionnement, quelle que soit l'orientation de l'appareil.setFinishPrimaryWithSecondary
: définit l'impact de toutes les activités effectuées dans le conteneur secondaire sur les activités du conteneur principal.NEVER
indique que le système ne doit pas terminer les activités principales lorsque toutes les activités du conteneur secondaire ont pris fin (voir Arrêter les activités).setFinishSecondaryWithPrimary
: définit l'impact de toutes les activités effectuées dans le conteneur principal sur les activités du conteneur secondaire.ALWAYS
indique que le système doit toujours terminer les activités dans le conteneur secondaire lorsque toutes les activités du conteneur principal ont pris fin (voir Arrêter les activités).setClearTop
: précise si toutes les activités dans le conteneur secondaire sont arrêtées lorsqu'une nouvelle activité est lancée dans le conteneur. La valeur "false" indique que les nouvelles activités sont empilées sur les activités déjà présentes dans le conteneur secondaire.
- Obtenez l'instance du singleton du
RuleController
de WindowManager, puis ajoutez la règle :
SplitManager.kt/createSplit()
val ruleController = RuleController.getInstance(context)
ruleController.addRule(splitPairRule)
SplitManager.java/createSplit()
RuleController ruleController = RuleController.getInstance(context);
ruleController.addRule(splitPairRule);
Créer une règle d'espace réservé
API requises :
SplitPlaceholderRule
définit une règle pour une activité qui occupe le conteneur secondaire lorsqu'aucun contenu n'est disponible pour ce conteneur spécifique. Pour créer une activité d'espace réservé, consultez "Créer une activité d'espace réservé" dans la section "Configuration XML" de cet atelier de programmation. Pour en savoir plus, consultez la section Espaces réservés dans le guide du développeur sur l'intégration d'activités.
SplitPlaceholderRule.Builder
crée une SplitPlaceholderRule
. Le compilateur utilise un ensemble d'objets ActivityFilter
comme argument. Les objets spécifient les activités auxquelles la règle d'espace réservé est associée. Si le filtre correspond à une activité démarrée, le système applique la règle d'espace réservé.
Vous devez enregistrer la règle avec le composant RuleController
.
Pour créer une règle d'espace réservé pour un fractionnement, procédez comme suit :
- Créez un
ActivityFilter
:
SplitManager.kt/createSplit()
val placeholderActivityFilter = ActivityFilter(
ComponentName(context, ListActivity::class.java),
null
)
SplitManager.java/createSplit()
ActivityFilter placeholderActivityFilter = new ActivityFilter(
new ComponentName(context, ListActivity.class),
null
);
Le filtre associe la règle à l'activité principale de l'application exemple, ListActivity
. Ainsi, lorsqu'aucun contenu détaillé n'est disponible dans la mise en page Liste/Détail, l'espace réservé remplit la zone de détail.
Le filtre peut inclure une action d'intent (deuxième paramètre) pour le lancement de l'activité associée (lancement de ListActivity
). Si vous incluez une action d'intent, le filtre la recherche avec le nom de l'activité. Pour les activités de votre propre application, vous ne filtrerez probablement pas les actions d'intent. L'argument peut donc être nul.
- Ajoutez le filtre à un ensemble de filtres :
SplitManager.kt/createSplit()
val placeholderActivityFilterSet = setOf(placeholderActivityFilter)
SplitManager.java/createSplit()
Set<ActivityFilter> placeholderActivityFilterSet = new HashSet<>();
placeholderActivityFilterSet.add(placeholderActivityFilter);
- Créez une
SplitPlaceholderRule
:
SplitManager.kt/createSplit()
val splitPlaceholderRule = SplitPlaceholderRule.Builder(
placeholderActivityFilterSet,
Intent(context, PlaceholderActivity::class.java)
).setDefaultSplitAttributes(splitAttributes)
.setMinWidthDp(840)
.setMinSmallestWidthDp(600)
.setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
.build()
SplitManager.java/createSplit()
SplitPlaceholderRule splitPlaceholderRule = new SplitPlaceholderRule.Builder(
placeholderActivityFilterSet,
new Intent(context, PlaceholderActivity.class)
).setDefaultSplitAttributes(splitAttributes)
.setMinWidthDp(840)
.setMinSmallestWidthDp(600)
.setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
.build();
SplitPlaceholderRule.Builder
crée et configure la règle :
placeholderActivityFilterSet
: contient les filtres d'activité qui déterminent quand appliquer la règle en identifiant les activités auxquelles l'activité d'espace réservé est associée.Intent
: spécifie le lancement de l'activité d'espace réservé.setDefaultSplitAttributes
: applique des attributs de mise en page à la règle.setMinWidthDp
: définit la largeur d'affichage minimale (en pixels indépendants de la densité, dp) pour permettre le fractionnement.setMinSmallestWidthDp
: définit la valeur minimale (en dp) que la plus petite des deux dimensions d'affichage doit avoir pour permettre un fractionnement, quelle que soit l'orientation de l'appareil.setFinishPrimaryWithPlaceholder
: définit l'impact de la finalisation de l'activité liée à un espace réservé sur les activités du conteneur principal.ALWAYS
indique que le système doit toujours terminer les activités dans le conteneur principal lorsque l'espace réservé a pris fin (voir Arrêter les activités).
- Ajoutez la règle à la fenêtre
RuleController
de WindowManager :
SplitManager.kt/createSplit()
ruleController.addRule(splitPlaceholderRule)
SplitManager.java/createSplit()
ruleController.addRule(splitPlaceholderRule);
Créer une règle d'activité
API requises :
ActivityRule
permet de définir une règle pour une activité qui occupera la totalité de la fenêtre de tâches, comme une boîte de dialogue modale. Pour en savoir plus, consultez l'article Fenêtre modale plein écran du guide du développeur sur l'intégration d'activités.
SplitPlaceholderRule.Builder
crée une SplitPlaceholderRule
. Le compilateur utilise un ensemble d'objets ActivityFilter
comme argument. Les objets spécifient les activités auxquelles la règle d'espace réservé est associée. Si le filtre correspond à une activité démarrée, le système applique la règle d'espace réservé.
Vous devez enregistrer la règle avec le composant RuleController
.
Pour créer une règle d'activité, procédez comme suit :
- Créez un
ActivityFilter
:
SplitManager.kt/createSplit()
val summaryActivityFilter = ActivityFilter(
ComponentName(context, SummaryActivity::class.java),
null
)
SplitManager.java/createSplit()
ActivityFilter summaryActivityFilter = new ActivityFilter(
new ComponentName(context, SummaryActivity.class),
null
);
Le filtre spécifie l'activité à laquelle la règle s'applique, SummaryActivity
.
Le filtre peut inclure une action d'intent (deuxième paramètre) pour le lancement de l'activité associée (lancement de SummaryActivity
). Si vous incluez une action d'intent, le filtre la recherche avec le nom de l'activité. Pour les activités de votre propre application, vous ne filtrerez probablement pas les actions d'intent. L'argument peut donc être nul.
- Ajoutez le filtre à un ensemble de filtres :
SplitManager.kt/createSplit()
val summaryActivityFilterSet = setOf(summaryActivityFilter)
SplitManager.java/createSplit()
Set<ActivityFilter> summaryActivityFilterSet = new HashSet<>();
summaryActivityFilterSet.add(summaryActivityFilter);
- Créez une
ActivityRule
:
SplitManager.kt/createSplit()
val activityRule = ActivityRule.Builder(summaryActivityFilterSet)
.setAlwaysExpand(true)
.build()
SplitManager.java/createSplit()
ActivityRule activityRule = new ActivityRule.Builder(
summaryActivityFilterSet
).setAlwaysExpand(true)
.build();
ActivityRule.Builder
crée et configure la règle :
summaryActivityFilterSet
: contient les filtres d'activité qui déterminent quand appliquer la règle en identifiant les activités que vous souhaitez exclure des écrans fractionnés.setAlwaysExpand
: indique si l'activité doit se développer pour occuper tout l'espace d'affichage disponible.
- Ajoutez la règle à la fenêtre
RuleController
de WindowManager :
SplitManager.kt/createSplit()
ruleController.addRule(activityRule)
SplitManager.java/createSplit()
ruleController.addRule(activityRule);
Exécuter le code
Créer et exécuter l'application exemple
L'application devrait se comporter de la même manière que lorsqu'elle est personnalisée à l'aide d'un fichier de configuration XML.
Consultez la section "Exécuter le code" dans la section "Configuration XML" de cet atelier de programmation.
Bonus
Essayez de définir le format dans l'application exemple à l'aide des méthodes setMaxAspectRatioInPortrait
et setMaxAspectRatioInLandscape
de SplitPairRule.Builder
et SplitPlaceholderRule.Builder
. Spécifiez les valeurs avec les propriétés et les méthodes de la classe EmbeddingAspectRatio
, par exemple :
SplitPairRule.Builder(filterSet)
. . .
.setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
. . .
.build()
Testez les paramètres avec votre grande tablette ou l'émulateur Pixel C.
Déterminez le format portrait de votre grande tablette (celui de la Pixel C est légèrement supérieur à 1,4). Définissez des valeurs supérieures et inférieures au format de votre tablette ou de la Pixel C pour le format maximal en mode portrait. Essayez les propriétés ALWAYS_ALLOW
et ALWAYS_DISALLOW
.
Exécutez l'application et observez les résultats.
Pour en savoir plus, consultez la section "Format" dans la section "Configuration XML" de cet atelier de programmation.
7. Navigation Material Design
Les consignes Material Design prévoient différents composants de navigation en fonction de la taille de l'écran : un rail de navigation pour les écrans d'une taille supérieure ou égale à 840 dp, une barre de navigation inférieure pour les écrans d'une taille inférieure à 840 dp.
Avec l'intégration d'activités, vous ne pouvez pas utiliser les méthodes getCurrentWindowMetrics()
et getMaximumWindowMetrics()
de WindowManager
pour déterminer la largeur de l'écran, car les métriques de fenêtre renvoyées par ces méthodes décrivent le volet d'affichage qui contient l'activité intégrée qui a appelé ces méthodes.
Pour obtenir les dimensions exactes de votre application d'intégration d'activités, utilisez un calculateur d'attributs de fractionnement et SplitAttributesCalculatorParams.
Supprimez les lignes suivantes si vous les avez ajoutées dans une section précédente.
main_split_config.xml
<SplitPairRule
. . .
window:splitMaxAspectRatioInPortrait="alwaysAllow" // Delete this line.
window:splitMaxAspectRatioInLandscape="alwaysDisallow" // Delete this line.
. . .>
</SplitPairRule>
<SplitPlaceholderRule
. . .
window:splitMaxAspectRatioInPortrait="alwaysAllow" // Delete this line.
window:splitMaxAspectRatioInLandscape="alwaysDisallow" // Delete this line.
. . .>
<SplitPlaceholderRule/>
Navigation flexible
Pour changer dynamiquement les composants de navigation en fonction de la taille de l'écran, utilisez un calculateur SplitAttributes
. Le calculateur détecte les changements d'orientation de l'appareil ainsi que la taille de la fenêtre, et recalcule les dimensions de l'écran en conséquence. Nous intégrerons un calculateur à SplitController
afin de déclencher les modifications des composants de navigation en fonction des changements de taille de l'écran.
Créer une mise en page de navigation
Tout d'abord, créez un menu que nous utiliserons pour remplir le rail et la barre de navigation.
Dans le dossier res/menu
, créez un nouveau fichier de ressources de menu que vous nommerez nav_menu.xml
. Remplacez le contenu du fichier de menu par le suivant :
nav_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_home"
android:title="Home" />
<item
android:id="@+id/navigation_dashboard"
android:title="Dashboard" />
<item
android:id="@+id/navigation_settings"
android:title="Settings" />
</menu>
Ensuite, ajoutez une barre de navigation et un rail de navigation à votre mise en page. Définissez leur visibilité sur gone
pour qu'ils soient initialement masqués. Nous les rendrons visibles en fonction des dimensions de la mise en page ultérieurement.
activity_list.xml
<com.google.android.material.navigationrail.NavigationRailView
android:id="@+id/navigationRailView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:menu="@menu/nav_menu"
android:visibility="gone" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavigationView"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:menu="@menu/nav_menu"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:visibility="gone" />
Écrivez une fonction pour gérer le basculement entre la barre de navigation et le rail de navigation.
ListActivity.kt / setWiderScreenNavigation()
private fun setWiderScreenNavigation(useNavRail: Boolean) {
val navRail = findViewById(R.id.navigationRailView)
val bottomNav = findViewById(R.id.bottomNavigationView)
if (useNavRail) {
navRail.visibility = View.VISIBLE
bottomNav.visibility = View.GONE
} else {
navRail.visibility = View.GONE
bottomNav.visibility = View.VISIBLE
}
}
ListActivity.java / setWiderScreenNavigation()
private void setWiderScreenNavigation(boolean useNavRail) {
NavigationRailView navRail = findViewById(R.id.navigationRailView);
BottomNavigationView bottomNav = findViewById(R.id.bottomNavigationView);
if (useNavRail) {
navRail.setVisibility(View.VISIBLE);
bottomNav.setVisibility(View.GONE);
} else {
navRail.setVisibility(View.GONE);
bottomNav.setVisibility(View.VISIBLE);
}
}
Calculateur d'attributs de fractionnement
SplitController
obtient des informations sur les fractionnements d'activités actuellement actives et fournit des points d'interaction permettant de personnaliser les fractionnements et d'en créer de nouvelles.
Dans les sections précédentes, nous avons défini les attributs par défaut des fractionnements en spécifiant splitRatio
et d'autres attributs dans les balises <SplitPairRule>
et <SplitPlaceHolderRule>
des fichiers XML ou en utilisant les API SplitPairRule.Builder#setDefaultSplitAttributes()
et SplitPlaceholderRule.Builder#setDefaultSplitAttributes()
.
Les attributs de fractionnement par défaut sont appliqués si les WindowMetrics du conteneur parent satisfont aux exigences de dimension de SplitRule, à savoir minWidthDp, minHeightDp et minSmallestWidthDp.
Nous allons mettre en place un calculateur d'attributs de fractionnement pour remplacer les attributs de fractionnement par défaut. Le calculateur met à jour les paires de fractionnement existantes après un changement d'état de la fenêtre ou de l'appareil, tel qu'un changement d'orientation ou un changement d'état de pliage.
Cela permet aux développeurs d'apprendre l'état de l'appareil ou de la fenêtre et de définir différents attributs de fractionnement dans différents scénarios, y compris l'orientation portrait et paysage ainsi que la position écran à plat.
Lors de la création d'un calculateur d'attributs de fractionnement, la plate-forme transmet un objet SplitAttributesCalculatorParams
à la fonction setSplitAttributesCalculator()
. La propriété parentWindowMetrics
fournit des métriques sur les fenêtres d'application.
Dans le code suivant, l'activité vérifie si les contraintes par défaut sont respectées, c'est-à-dire largeur > 840 dp et plus petite largeur > 600 dp. Lorsque les conditions sont remplies, les activités sont intégrées dans une mise en page à double volet et l'application utilise un rail de navigation au lieu d'une barre de navigation inférieure. Dans le cas contraire, les activités sont affichées en plein écran avec une barre de navigation inférieure.
ListActivity.kt / setSplitAttributesCalculator()
SplitController.getInstance(this).setSplitAttributesCalculator
params ->
if (params.areDefaultConstraintsSatisfied) {
// When default constraints are satisfied, use the navigation rail.
setWiderScreenNavigation(true)
return@setSplitAttributesCalculator params.defaultSplitAttributes
} else {
// Use the bottom navigation bar in other cases.
setWiderScreenNavigation(false)
// Expand containers if the device is in portrait or the width is less than 840 dp.
SplitAttributes.Builder()
.setSplitType(SPLIT_TYPE_EXPAND)
.build()
}
}
ListActivity.java / setSplitAttributesCalculator()
SplitController.getInstance(this).setSplitAttributesCalculator(params -> {
if (params.areDefaultConstraintsSatisfied()) {
// When default constraints are satisfied, use the navigation rail.
setWiderScreenNavigation(true);
return params.getDefaultSplitAttributes();
} else {
// Use the bottom navigation bar in other cases.
setWiderScreenNavigation(false);
// Expand containers if the device is in portrait or the width is less than 600 dp.
return new SplitAttributes.Builder()
.setSplitType(SplitType.SPLIT_TYPE_EXPAND)
.build();
}
});
Bravo, votre application d'intégration d'activités respecte désormais les consignes de navigation Material Design !
8. Félicitations !
Bravo ! Vous venez d'optimiser une application basée sur des activités pour une mise en page Liste/Détail sur les grands écrans et d'ajouter la navigation Material Design.
Vous avez appris deux façons d'implémenter l'intégration d'activités :
- Via un fichier de configuration XML
- Via des appels d'API Jetpack
- Via l'implémentation d'une navigation flexible avec l'intégration d'activités
Vous n'avez pas eu à réécrire le code source Kotlin ou Java de l'application.
Vous êtes maintenant prêt à optimiser vos applications de production pour les grands écrans grâce à l'intégration d'activités.
9. En savoir plus
- Guide du développeur : Intégration d'activités
- Documentation de référence : androidx.window.embedding