Rotation de la gestion
Cette rubrique explique comment gérer les modifications d’orientation de l’appareil dans Xamarin.Android. Il explique comment utiliser le système de ressources Android pour charger automatiquement des ressources pour une orientation particulière de l’appareil et comment gérer par programme les modifications d’orientation.
Vue d’ensemble
Étant donné que les appareils mobiles sont facilement pivotés, la rotation intégrée est une fonctionnalité standard des systèmes d’exploitation mobiles. Android fournit une infrastructure sophistiquée pour gérer la rotation au sein des applications, que l’interface utilisateur soit créée de manière déclarative en XML ou par programmation dans le code. Lorsque vous gérez automatiquement les modifications de disposition déclaratives sur un appareil pivoté, une application peut bénéficier de l’intégration étroite avec le système de ressources Android. Pour la disposition programmatique, les modifications doivent être gérées manuellement. Cela permet un contrôle plus fin au moment de l’exécution, mais au détriment de plus de travail pour le développeur. Une application peut également choisir de désactiver le redémarrage de l’activité et de prendre un contrôle manuel des modifications d’orientation.
Ce guide examine les rubriques d’orientation suivantes :
Rotation déclarative de la disposition : comment utiliser le système de ressources Android pour créer des applications prenant en charge l’orientation, notamment la façon de charger à la fois des dispositions et des dessins pour des orientations particulières.
Rotation de disposition programmatique : comment ajouter des contrôles par programmation, ainsi que comment gérer manuellement les modifications d’orientation.
Gestion de la rotation de manière déclarative avec des dispositions
En incluant des fichiers dans des dossiers qui suivent les conventions d’affectation de noms, Android charge automatiquement les fichiers appropriés lorsque l’orientation change. Cela inclut la prise en charge des éléments suivants :
Ressources de disposition : spécification des fichiers de disposition gonflés pour chaque orientation.
Ressources dessinables : spécification des tiroirs chargés pour chaque orientation.
Ressources de disposition
Par défaut, les fichiers Android XML (AXML) inclus dans le dossier Ressources/disposition sont utilisés pour le rendu des vues pour une activité. Les ressources de ce dossier sont utilisées pour l’orientation portrait et paysage si aucune ressource de disposition supplémentaire n’est fournie spécifiquement pour le paysage. Considérez la structure du projet créée par le modèle de projet par défaut :
Ce projet crée un seul fichier Main.axml dans le dossier Resources/layout . Lorsque la méthode de l’activité OnCreate
est appelée, elle gonfle la vue définie dans Main.axml, qui déclare un bouton comme indiqué dans le code XML ci-dessous :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/myButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"/>
</LinearLayout>
Si l’appareil est pivoté vers l’orientation paysage, la méthode de l’activité OnCreate
est appelée à nouveau et le même fichier Main.axml est gonflé, comme illustré dans la capture d’écran ci-dessous :
Dispositions spécifiques à l’orientation
Outre le dossier de disposition (qui est défini par défaut sur portrait et peut également être explicitement nommé layout-port en incluant un dossier nommé layout-land
), une application peut définir les vues dont elle a besoin lorsqu’elle est en paysage sans aucune modification du code.
Supposons que le fichier Main.axml contenait le code XML suivant :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="This is portrait"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
</RelativeLayout>
Si un dossier nommé layout-land qui contient un fichier Main.axml supplémentaire est ajouté au projet, l’inflation de la disposition lorsque le paysage entraîne désormais le chargement Android du fichier Main.axml nouvellement ajouté. Considérez la version paysage du fichier Main.axml qui contient le code suivant (par souci de simplicité, ce code XML est similaire à la version portrait par défaut du code, mais utilise une chaîne différente dans le TextView
code) :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="This is landscape"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
</RelativeLayout>
L’exécution de ce code et la rotation de l’appareil de portrait en paysage illustre le nouveau chargement XML, comme indiqué ci-dessous :
Ressources dessinables
Pendant la rotation, Android traite les ressources dessinables de la même façon que les ressources de disposition. Dans ce cas, le système obtient les tiroirs des dossiers Ressources/dessinables et Ressources/terrains dessinables , respectivement.
Par exemple, supposons que le projet inclut une image nommée Monkey.png dans le dossier Ressources/dessinable, où le dessinable est référencé à partir d’un ImageView
fichier XML comme suit :
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/monkey"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
Supposons également qu’une autre version de Monkey.png est incluse dans les ressources/terrains dessinables. Tout comme avec les fichiers de disposition, lorsque l’appareil est pivoté, les modifications dessinables pour l’orientation donnée, comme indiqué ci-dessous :
Gestion de la rotation par programmation
Parfois, nous définissons des dispositions dans le code. Cela peut se produire pour diverses raisons, notamment les limitations techniques, les préférences des développeurs, etc. Lorsque nous ajoutons des contrôles par programmation, une application doit prendre en compte manuellement l’orientation de l’appareil, qui est gérée automatiquement lorsque nous utilisons des ressources XML.
Ajout de contrôles dans le code
Pour ajouter des contrôles par programmation, une application doit effectuer les étapes suivantes :
- Créez une disposition.
- Définissez les paramètres de disposition.
- Créez des contrôles.
- Définissez les paramètres de disposition du contrôle.
- Ajoutez des contrôles à la disposition.
- Définissez la disposition en tant qu’affichage de contenu.
Par exemple, considérez une interface utilisateur composée d’un seul TextView
contrôle ajouté à un RelativeLayout
, comme illustré dans le code suivant.
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// create a layout
var rl = new RelativeLayout (this);
// set layout parameters
var layoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.FillParent);
rl.LayoutParameters = layoutParams;
// create TextView control
var tv = new TextView (this);
// set TextView's LayoutParameters
tv.LayoutParameters = layoutParams;
tv.Text = "Programmatic layout";
// add TextView to the layout
rl.AddView (tv);
// set the layout as the content view
SetContentView (rl);
}
Ce code crée une instance d’une RelativeLayout
classe et définit sa LayoutParameters
propriété. La LayoutParams
classe est la façon d’encapsuler la façon dont les contrôles sont positionnés de manière réutilisable. Une fois qu’une instance d’une disposition est créée, les contrôles peuvent être créés et ajoutés à celui-ci. Les contrôles ont LayoutParameters
également , comme dans TextView
cet exemple. Une fois la TextView
création terminée, l’ajout de celui-ci à la RelativeLayout
RelativeLayout
vue de contenu entraîne l’affichage de contenu dans l’application, TextView
comme indiqué ci-dessous :
Détection de l’orientation dans le code
Si une application tente de charger une interface utilisateur différente pour chaque orientation lorsqu’elle OnCreate
est appelée (cela se produit chaque fois qu’un appareil est pivoté), il doit détecter l’orientation, puis charger le code d’interface utilisateur souhaité. Android a une classe appelée WindowManager
, qui peut être utilisée pour déterminer la rotation actuelle de l’appareil via la WindowManager.DefaultDisplay.Rotation
propriété, comme indiqué ci-dessous :
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// create a layout
var rl = new RelativeLayout (this);
// set layout parameters
var layoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.FillParent);
rl.LayoutParameters = layoutParams;
// get the initial orientation
var surfaceOrientation = WindowManager.DefaultDisplay.Rotation;
// create layout based upon orientation
RelativeLayout.LayoutParams tvLayoutParams;
if (surfaceOrientation == SurfaceOrientation.Rotation0 || surfaceOrientation == SurfaceOrientation.Rotation180) {
tvLayoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
} else {
tvLayoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
tvLayoutParams.LeftMargin = 100;
tvLayoutParams.TopMargin = 100;
}
// create TextView control
var tv = new TextView (this);
tv.LayoutParameters = tvLayoutParams;
tv.Text = "Programmatic layout";
// add TextView to the layout
rl.AddView (tv);
// set the layout as the content view
SetContentView (rl);
}
Ce code définit la TextView
position à positionner 100 pixels à partir du haut à gauche de l’écran, en animant automatiquement la nouvelle disposition, lorsqu’elle est pivotée vers le paysage, comme illustré ici :
Empêcher le redémarrage de l’activité
Outre la gestion de tout ce qui se trouve, OnCreate
une application peut également empêcher le redémarrage d’une activité lorsque l’orientation change en définissant ConfigurationChanges
dans les ActivityAttribute
étapes suivantes :
[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
À présent, lorsque l’appareil est pivoté, l’activité n’est pas redémarrée. Pour gérer manuellement le changement d’orientation dans ce cas, une activité peut remplacer la OnConfigurationChanged
méthode et déterminer l’orientation de l’objet Configuration
passé, comme dans la nouvelle implémentation de l’activité ci-dessous :
[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
public class CodeLayoutActivity : Activity
{
TextView _tv;
RelativeLayout.LayoutParams _layoutParamsPortrait;
RelativeLayout.LayoutParams _layoutParamsLandscape;
protected override void OnCreate (Bundle bundle)
{
// create a layout
// set layout parameters
// get the initial orientation
// create portrait and landscape layout for the TextView
_layoutParamsPortrait = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
_layoutParamsLandscape = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
_layoutParamsLandscape.LeftMargin = 100;
_layoutParamsLandscape.TopMargin = 100;
_tv = new TextView (this);
if (surfaceOrientation == SurfaceOrientation.Rotation0 || surfaceOrientation == SurfaceOrientation.Rotation180) {
_tv.LayoutParameters = _layoutParamsPortrait;
} else {
_tv.LayoutParameters = _layoutParamsLandscape;
}
_tv.Text = "Programmatic layout";
rl.AddView (_tv);
SetContentView (rl);
}
public override void OnConfigurationChanged (Android.Content.Res.Configuration newConfig)
{
base.OnConfigurationChanged (newConfig);
if (newConfig.Orientation == Android.Content.Res.Orientation.Portrait) {
_tv.LayoutParameters = _layoutParamsPortrait;
_tv.Text = "Changed to portrait";
} else if (newConfig.Orientation == Android.Content.Res.Orientation.Landscape) {
_tv.LayoutParameters = _layoutParamsLandscape;
_tv.Text = "Changed to landscape";
}
}
}
Ici, les TextView's
paramètres de disposition sont initialisés pour le paysage et le portrait. Les variables de classe contiennent les paramètres, ainsi que l’activité TextView
elle-même, car l’activité ne sera pas recréé lorsque l’orientation change. Le code utilise toujours l’entrée surfaceOrientartion
OnCreate
pour définir la disposition initiale pour le TextView
. Après cela, OnConfigurationChanged
gère toutes les modifications de disposition suivantes.
Lorsque nous exécutons l’application, Android charge les modifications apportées à l’interface utilisateur à mesure que la rotation de l’appareil se produit et ne redémarre pas l’activité.
Prévention du redémarrage de l’activité pour les dispositions déclaratives
Les redémarrages d’activité provoqués par la rotation de l’appareil peuvent également être empêchés si nous définissons la disposition en XML. Par exemple, nous pouvons utiliser cette approche si nous voulons empêcher un redémarrage d’activité (pour des raisons de performances, peut-être) et nous n’avons pas besoin de charger de nouvelles ressources pour différentes orientations.
Pour ce faire, nous suivons la même procédure que celle que nous utilisons avec une disposition programmatique. Il suffit de définir ConfigurationChanges
dans le ActivityAttribute
, comme nous l’avons CodeLayoutActivity
fait précédemment. Tout code qui doit s’exécuter pour la modification d’orientation peut à nouveau être implémenté dans la OnConfigurationChanged
méthode.
Maintien de l’état pendant les modifications d’orientation
Que la gestion de la rotation soit déclarative ou programmatique, toutes les applications Android doivent implémenter les mêmes techniques de gestion de l’état lorsque l’orientation de l’appareil change. La gestion de l’état est importante, car le système redémarre une activité en cours d’exécution lorsqu’un appareil Android est pivoté. Android le fait pour faciliter le chargement de ressources alternatives, telles que des dispositions et des dessins conçus spécifiquement pour une orientation particulière. Quand elle redémarre, l’activité perd tout état temporaire qu’elle peut avoir stocké dans des variables de classe locale. Par conséquent, si une activité dépend de l’état, elle doit conserver son état au niveau de l’application. Une application doit gérer l’enregistrement et la restauration de tout état d’application qu’elle souhaite conserver dans les modifications d’orientation.
Pour plus d’informations sur la persistance de l’état dans Android, reportez-vous au guide de cycle de vie des activités.
Résumé
Cet article a abordé comment utiliser les fonctionnalités intégrées d’Android pour fonctionner avec la rotation. Tout d’abord, il a expliqué comment utiliser le système de ressources Android pour créer des applications prenant en charge l’orientation. Il a ensuite présenté comment ajouter des contrôles dans le code, ainsi que comment gérer manuellement les modifications d’orientation.