Mises en page dans les vues
Une mise en page définit la structure d'une interface utilisateur dans votre application, par exemple dans une activité. Tous les éléments de la mise en page sont créés à l'aide d'une hiérarchie d'objets View et ViewGroup. Un View montre généralement un élément avec lequel les utilisateurs peuvent interagir. Un ViewGroup est un conteneur invisible qui définit la structure de mise en page pour View et d'autres objets ViewGroup, comme illustré à la figure 1.
Les objets View sont souvent appelés widgets et peuvent appartenir à l'une des nombreuses sous-classes, telles que Button ou TextView. Les objets ViewGroup sont généralement appelés mises en page et peuvent être de différents types qui fournissent une structure de mise en page différente, comme LinearLayout ou ConstraintLayout.
Vous pouvez déclarer une mise en page de deux manières :
- Déclarez les éléments d'interface utilisateur dans le fichier XML. Android fournit un vocabulaire XML simple qui correspond aux classes et sous-classes
View, telles que celles pour les widgets et les mises en page. Vous pouvez également utiliser l'éditeur de mise en page d'Android Studio pour créer votre mise en page XML à l'aide d'une interface de glisser-déposer. - Instanciez les éléments de mise en page au moment de l'exécution. Votre application peut créer des objets
ViewetViewGroup, et manipuler leurs propriétés de manière programmatique.
Déclarer votre UI en XML vous permet de séparer la présentation de votre application du code qui contrôle son comportement. L'utilisation de fichiers XML facilite également la fourniture de mises en page différentes pour différentes tailles et orientations d'écran. Pour en savoir plus, consultez Compatibilité avec différentes tailles d'écran.
Le framework Android vous permet d'utiliser l'une ou l'autre de ces méthodes, ou les deux, pour créer l'UI de votre application. Par exemple, vous pouvez déclarer les mises en page par défaut de votre application en XML, puis modifier la mise en page au moment de l'exécution.
Écrire le fichier XML
En utilisant le vocabulaire XML d'Android, vous pouvez concevoir rapidement des mises en page d'UI et les éléments d'écran qu'elles contiennent, de la même manière que vous créez des pages Web en HTML avec une série d'éléments imbriqués.
Chaque fichier de mise en page doit contenir exactement un élément racine, qui doit être un objet View ou ViewGroup. Une fois que vous avez défini l'élément racine, vous pouvez ajouter des objets de mise en page ou des widgets supplémentaires en tant qu'éléments enfants pour créer progressivement une hiérarchie View qui définit votre mise en page. Par exemple, voici une mise en page XML qui utilise un LinearLayout vertical pour contenir un TextView et un Button :
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a Button" /> </LinearLayout>
Après avoir déclaré votre mise en page en XML, enregistrez le fichier avec l'extension .xml dans le répertoire res/layout/ de votre projet Android pour qu'il se compile correctement.
Pour en savoir plus sur la syntaxe d'un fichier XML de mise en page, consultez Ressource de mise en page.
Charger la ressource XML
Lorsque vous compilez votre application, chaque fichier de mise en page XML est compilé en ressource View. Chargez la ressource de mise en page dans l'implémentation du rappel Activity.onCreate() de votre application. Pour ce faire, appelez setContentView() en lui transmettant la référence à votre ressource de mise en page sous la forme R.layout.layout_file_name. Par exemple, si votre mise en page XML est enregistrée sous le nom main_layout.xml, chargez-la pour votre Activity comme suit :
Kotlin
fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) setContentView(R.layout.main_layout) }
Java
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); }
Le framework Android appelle la méthode de rappel onCreate() dans votre Activity lorsque le Activity est lancé. Pour en savoir plus sur les cycles de vie des activités, consultez Présentation des activités.
Attributs
Chaque objet View et ViewGroup accepte sa propre variété d'attributs XML. Certains attributs sont spécifiques à un objet View. Par exemple, TextView est compatible avec l'attribut textSize. Toutefois, ces attributs sont également hérités par tous les objets View qui étendent cette classe. Certains sont communs à tous les objets View, car ils sont hérités de la classe racine View, comme l'attribut id. Les autres attributs sont considérés comme des paramètres de mise en page, c'est-à-dire des attributs qui décrivent certaines orientations de mise en page de l'objet View, telles que définies par l'objet ViewGroup parent.
ID
Tout objet View peut être associé à un ID entier pour identifier de manière unique le View dans l'arborescence. Lorsque l'application est compilée, cet ID est référencé en tant qu'entier, mais il est généralement attribué dans le fichier XML de mise en page en tant que chaîne dans l'attribut id. Il s'agit d'un attribut XML commun à tous les objets View, défini par la classe View. Vous l'utilisez très souvent. La syntaxe d'un ID dans une balise XML est la suivante :
android:id="@+id/my_button"
Le symbole at (@) au début de la chaîne indique que l'analyseur XML analyse et développe le reste de la chaîne d'ID, et l'identifie comme une ressource d'ID. Le symbole plus (+) signifie qu'il s'agit d'un nouveau nom de ressource qui doit être créé et ajouté à vos ressources dans le fichier R.java.
Le framework Android propose de nombreuses autres ressources d'ID. Lorsque vous faites référence à un ID de ressource Android, vous n'avez pas besoin du symbole plus, mais vous devez ajouter l'espace de noms du package android comme suit :
android:id="@android:id/empty"
L'espace de noms du package android indique que vous faites référence à un ID de la classe de ressources android.R, plutôt qu'à la classe de ressources locale.
Pour créer des vues et les référencer depuis votre application, vous pouvez utiliser un modèle commun comme suit :
- Définissez une vue dans le fichier de mise en page et attribuez-lui un ID unique, comme dans l'exemple suivant :
<Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/my_button_text"/>
- Créez une instance de l'objet de vue et capturez-la à partir de la mise en page, généralement dans la méthode
onCreate(), comme illustré dans l'exemple suivant :Kotlin
val myButton: Button = findViewById(R.id.my_button)
Java
Button myButton = (Button) findViewById(R.id.my_button);
Il est important de définir des ID pour les objets de vue lorsque vous créez un RelativeLayout.
Dans une mise en page relative, les vues frères peuvent définir leur mise en page par rapport à une autre vue frère, référencée par l'ID unique.
Un ID n'a pas besoin d'être unique dans l'ensemble de l'arborescence, mais il doit l'être dans la partie de l'arborescence que vous recherchez. Il s'agit souvent de l'arborescence entière. Il est donc préférable de la rendre unique dans la mesure du possible.
Paramètres de mise en page
Les attributs de mise en page XML nommés layout_something définissent les paramètres de mise en page du View qui conviennent au ViewGroup dans lequel il se trouve.
Chaque classe ViewGroup implémente une classe imbriquée qui étend ViewGroup.LayoutParams.
Cette sous-classe contient des types de propriétés qui définissent la taille et la position de chaque vue enfant, selon le groupe de vues. Comme le montre la figure 2, le groupe de vues parent définit les paramètres de mise en page pour chaque vue enfant, y compris le groupe de vues enfant.
Chaque sous-classe LayoutParams possède sa propre syntaxe pour définir des valeurs. Chaque élément enfant doit définir un LayoutParams adapté à son parent, mais il peut également définir un LayoutParams différent pour ses propres enfants.
Tous les groupes de vues incluent une largeur et une hauteur, à l'aide de layout_width et layout_height, et chaque vue doit les définir. De nombreux LayoutParams incluent des marges et des bordures facultatives.
Vous pouvez spécifier la largeur et la hauteur avec des mesures exactes, mais vous ne voudrez probablement pas le faire souvent. Le plus souvent, vous utilisez l'une de ces constantes pour définir la largeur ou la hauteur :
wrap_content: indique à votre vue de se dimensionner selon les dimensions requises par son contenu.match_parent: indique à votre vue de devenir aussi grande que le permet son groupe de vues parent.
En général, nous vous déconseillons de spécifier la largeur et la hauteur d'une mise en page à l'aide d'unités absolues telles que les pixels. Une meilleure approche consiste à utiliser des mesures relatives, telles que les unités de pixels indépendants de la densité (dp), wrap_content ou match_parent, car cela permet à votre application de s'afficher correctement sur différentes tailles d'écran d'appareils. Les types de mesures acceptés sont définis dans Ressource de mise en page.
Position de la mise en page
Une vue a une géométrie rectangulaire. Il possède un emplacement, exprimé sous la forme d'une paire de coordonnées left et top, et deux dimensions, exprimées sous la forme d'une largeur et d'une hauteur. L'unité de mesure pour l'emplacement et les dimensions est le pixel.
Vous pouvez récupérer l'emplacement d'une vue en appelant les méthodes getLeft() et getTop().
La première renvoie la coordonnée de gauche (x) du rectangle représentant la vue. Cette dernière renvoie la coordonnée supérieure (y) du rectangle représentant la vue. Ces méthodes renvoient l'emplacement de la vue par rapport à son parent. Par exemple, lorsque getLeft() renvoie la valeur 20, cela signifie que la vue est située 20 pixels à droite du bord gauche de son parent direct.
De plus, il existe des méthodes pratiques pour éviter les calculs inutiles : getRight() et getBottom().
Ces méthodes renvoient les coordonnées des bords droit et inférieur du rectangle représentant la vue. Par exemple, l'appel de getRight() est semblable au calcul suivant : getLeft() + getWidth().
Taille, marge intérieure et marges
La taille d'une vue est exprimée par une largeur et une hauteur. Une vue comporte deux paires de valeurs de largeur et de hauteur.
La première paire est appelée largeur mesurée et hauteur mesurée. Ces dimensions définissent la taille souhaitée d'une vue dans son parent. Vous pouvez obtenir les dimensions mesurées en appelant getMeasuredWidth() et getMeasuredHeight().
La deuxième paire est appelée width et height, ou parfois drawing width et drawing height. Ces dimensions définissent la taille réelle de la vue à l'écran, au moment du dessin et après la mise en page. Ces valeurs peuvent différer de la largeur et de la hauteur mesurées, mais ce n'est pas obligatoire. Vous pouvez obtenir la largeur et la hauteur en appelant getWidth() et getHeight().
Pour mesurer ses dimensions, une vue tient compte de sa marge intérieure. La marge intérieure est exprimée en pixels pour les parties gauche, supérieure, droite et inférieure de la vue.
Vous pouvez utiliser le remplissage pour décaler le contenu de la vue d'un nombre spécifique de pixels. Par exemple, une marge intérieure gauche de deux pixels décale le contenu de la vue de deux pixels vers la droite par rapport au bord gauche. Vous pouvez définir la marge intérieure à l'aide de la méthode setPadding(int, int, int, int) et l'interroger en appelant getPaddingLeft(), getPaddingTop(), getPaddingRight() et getPaddingBottom().
Bien qu'une vue puisse définir une marge intérieure, elle n'est pas compatible avec les marges extérieures. Toutefois, les groupes de vues sont compatibles avec les marges. Pour en savoir plus, consultez ViewGroup et ViewGroup.MarginLayoutParams.
Pour en savoir plus sur les dimensions, consultez Dimension.
En plus de définir les marges et les marges intérieures de manière programmatique, vous pouvez également les définir dans vos mises en page XML, comme illustré dans l'exemple suivant :
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="16dp" android:padding="8dp" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:paddingBottom="4dp" android:paddingEnd="8dp" android:paddingStart="8dp" android:paddingTop="4dp" android:text="Hello, I am a Button" /> </LinearLayout>
L'exemple précédent montre l'application des marges et des marges intérieures. TextView applique des marges et des marges intérieures uniformes tout autour, tandis que Button montre comment les appliquer indépendamment à différentes bordures.
Mises en page courantes
Chaque sous-classe de la classe ViewGroup fournit une manière unique d'afficher les vues que vous y imbriquez. ConstraintLayout est le type de mise en page le plus flexible et celui qui fournit les meilleurs outils pour maintenir une hiérarchie de mise en page peu profonde.
Voici quelques-uns des types de mise en page courants intégrés à la plate-forme Android.
Organise ses enfants en une seule ligne horizontale ou verticale et crée une barre de défilement si la longueur de la fenêtre dépasse celle de l'écran.
Créer des listes dynamiques
Lorsque le contenu de votre mise en page est dynamique ou non prédéterminé, vous pouvez utiliser RecyclerView ou une sous-classe de AdapterView.
RecyclerView est généralement la meilleure option, car elle utilise la mémoire plus efficacement que AdapterView.
Voici quelques exemples de mises en page courantes possibles avec RecyclerView et AdapterView :
RecyclerView offre plus de possibilités et l'option créer un gestionnaire de mise en page personnalisé.
Remplir une vue d'adaptateur avec des données
Vous pouvez remplir un AdapterView tel que ListView ou GridView en liant l'instance AdapterView à un Adapter, qui récupère les données d'une source externe et crée un View qui représente chaque entrée de données.
Android fournit plusieurs sous-classes de Adapter qui sont utiles pour récupérer différents types de données et créer des vues pour un AdapterView. Voici les deux adaptateurs les plus courants :
ArrayAdapter- Utilisez cet adaptateur lorsque votre source de données est un tableau. Par défaut,
ArrayAdaptercrée une vue pour chaque élément du tableau en appelanttoString()sur chaque élément et en plaçant le contenu dans unTextView.Par exemple, si vous avez un tableau de chaînes que vous souhaitez afficher dans un
ListView, initialisez un nouveauArrayAdapterà l'aide d'un constructeur pour spécifier la mise en page de chaque chaîne et du tableau de chaînes :Kotlin
val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray)
Java
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray);
Les arguments de ce constructeur sont les suivants :
- Votre application
Context - Mise en page contenant un
TextViewpour chaque chaîne du tableau - Tableau de chaînes
Appelez ensuite
setAdapter()sur votreListView:Kotlin
val listView: ListView = findViewById(R.id.listview) listView.adapter = adapter
Java
ListView listView = (ListView) findViewById(R.id.listview); listView.setAdapter(adapter);
Pour personnaliser l'apparence de chaque élément, vous pouvez remplacer la méthode
toString()pour les objets de votre tableau. Vous pouvez également créer une vue pour chaque élément autre qu'unTextView. Par exemple, si vous souhaitez unImageViewpour chaque élément de tableau, étendez la classeArrayAdapteret remplacezgetView()pour renvoyer le type de vue souhaité pour chaque élément. - Votre application
SimpleCursorAdapter- Utilisez cet adaptateur lorsque vos données proviennent d'un
Cursor. Lorsque vous utilisezSimpleCursorAdapter, spécifiez une mise en page à utiliser pour chaque ligne deCursoret les colonnes deCursorque vous souhaitez insérer dans les vues de la mise en page de votre choix. Par exemple, si vous souhaitez créer une liste de noms et de numéros de téléphone, vous pouvez exécuter une requête qui renvoie unCursorcontenant une ligne pour chaque personne et des colonnes pour les noms et les numéros. Vous créez ensuite un tableau de chaînes spécifiant les colonnes deCursorque vous souhaitez inclure dans la mise en page pour chaque résultat, ainsi qu'un tableau d'entiers spécifiant les vues correspondantes dans lesquelles chaque colonne doit être placée :Kotlin
val fromColumns = arrayOf(ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER) val toViews = intArrayOf(R.id.display_name, R.id.phone_number)
Java
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}; int[] toViews = {R.id.display_name, R.id.phone_number};
Lorsque vous instanciez
SimpleCursorAdapter, transmettez la mise en page à utiliser pour chaque résultat, leCursorcontenant les résultats et ces deux tableaux :Kotlin
val adapter = SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0) val listView = getListView() listView.adapter = adapter
Java
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0); ListView listView = getListView(); listView.setAdapter(adapter);
SimpleCursorAdaptercrée ensuite une vue pour chaque ligne deCursorà l'aide de la mise en page fournie en insérant chaque élémentfromColumnsdans la vuetoViewscorrespondante.
Si, au cours de la durée de vie de votre application, vous modifiez les données sous-jacentes lues par votre adaptateur, appelez notifyDataSetChanged().
Cela indique à la vue associée que les données ont été modifiées et qu'elle doit s'actualiser.
Gérer les événements de clic
Vous pouvez répondre aux événements de clic sur chaque élément d'un AdapterView en implémentant l'interface AdapterView.OnItemClickListener. Exemple :
Kotlin
listView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id -> // Do something in response to the click. }
Java
// Create a message handling object as an anonymous class. private OnItemClickListener messageClickedHandler = new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { // Do something in response to the click. } }; listView.setOnItemClickListener(messageClickedHandler);
Ressources supplémentaires
Découvrez comment les mises en page sont utilisées dans l'application de démonstration Sunflower sur GitHub.


