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
dessine généralement quelque chose que l'utilisateur peut voir et interagir. Un ViewGroup
est un conteneur invisible qui définit la structure de mise en page pour View
et les autres objets ViewGroup
, comme illustré dans la figure 1.
![](https://developer.android.com/static/images/viewgroup_2x.png?authuser=6&hl=fr)
Les objets View
sont souvent appelés widgets et peuvent correspondre à 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 plusieurs types qui offrent une structure de mise en page différente, par exemple LinearLayout
ou ConstraintLayout
.
Vous pouvez déclarer une mise en page de deux manières:
- Déclarez des éléments d'interface utilisateur au format XML. Android fournit un vocabulaire XML simple qui correspond aux classes et sous-classes
View
, comme celles des widgets et des 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 par glisser-déposer. - Instanciez les éléments de mise en page au moment de l'exécution. Votre application peut créer des objets
View
etViewGroup
, et manipuler leurs propriétés de manière programmatique.
La déclaration de votre UI au format XML vous permet de séparer la présentation de votre application du code qui contrôle son comportement. L'utilisation de fichiers XML permet également de fournir plus facilement différentes mises en page pour différentes tailles et orientations d'écran. Ce point est abordé plus en détail dans la section Assurer la compatibilité avec différentes tailles d'écran.
Le framework Android vous permet d'utiliser l'une de ces méthodes ou les deux pour créer l'interface utilisateur de votre application. Par exemple, vous pouvez déclarer les mises en page par défaut de votre application au format XML, puis modifier la mise en page au moment de l'exécution.
Écrire le code XML
Le vocabulaire XML d'Android vous permet de concevoir rapidement des mises en page d'interface utilisateur et les éléments 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
. Après avoir 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 élément LinearLayout
vertical pour contenir un élément TextView
et un élément 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 au format XML, enregistrez le fichier avec l'extension .xml
dans le répertoire res/layout/
de votre projet Android afin qu'il se compile correctement.
Pour en savoir plus sur la syntaxe d'un fichier XML de mise en page, consultez la section Ressource de mise en page.
Charger la ressource XML
Lorsque vous compilez votre application, chaque fichier de mise en page XML est compilé dans une 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()
et transmettez-lui la référence à votre ressource de mise en page au format R.layout.layout_file_name
. Par exemple, si votre mise en page XML est enregistrée sous 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
lors du lancement de l'Activity
. Pour en savoir plus sur les cycles de vie des activités, consultez la section 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
accepte l'attribut textSize
. Toutefois, ces attributs sont également hérités par les objets View
qui étendent cette classe. Certains sont communs à tous les objets View
, car ils sont hérités de la classe View
racine, comme l'attribut id
. Les autres attributs sont considérés comme des paramètres de mise en page. Ils décrivent certaines orientations de mise en page de l'objet View
, telles que définies par l'objet ViewGroup
parent de cet objet.
ID
Tout objet View
peut être associé à un ID entier pour identifier de manière unique la View
dans l'arborescence. Lorsque l'application est compilée, cet ID est référencé sous la forme d'un 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
, qui est 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, puis l'identifie en tant que 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 à partir de la classe de ressources android.R
, et non à partir de la classe de ressources locale.
Pour créer des vues et les référencer à partir de 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 View et capturez-le à partir de la mise en page, généralement à l'aide de 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 lors de la création d'un RelativeLayout
.
Dans une mise en page relative, les vues sœurs peuvent définir leur mise en page par rapport à une autre vue sœur, référencée par l'ID unique.
Un identifiant n'a pas besoin d'être unique dans l'ensemble de l'arborescence, mais doit être unique dans la partie de l'arborescence que vous recherchez. Il peut souvent s'agir de l'arborescence entière. Il est donc préférable de la rendre unique lorsque cela est 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 de l'View
adaptés 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, en fonction du 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.
![](https://developer.android.com/static/images/layoutparams.png?authuser=6&hl=fr)
Chaque sous-classe LayoutParams
possède sa propre syntaxe pour définir des valeurs. Chaque élément enfant doit définir une LayoutParams
appropriée pour son parent, bien qu'il puisse également définir une LayoutParams
différente 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 est nécessaire pour les définir. De nombreux éléments LayoutParams
incluent des marges et des bordures facultatives.
Vous pouvez spécifier la largeur et la hauteur avec des mesures exactes, mais vous ne souhaiterez peut-être pas le faire souvent. Le plus souvent, utilisez l'une de ces constantes pour définir la largeur ou la hauteur:
wrap_content
: indique à la vue de s'adapter aux dimensions requises par son contenu.match_parent
: indique à la vue de s'adapter à la taille du groupe de vues parent.
En général, nous vous déconseillons de spécifier une largeur et une hauteur de mise en page en utilisant des unités absolues telles que les pixels. Une meilleure approche consiste à utiliser des mesures relatives, telles que les unités de pixels indépendantes de la densité (dp), wrap_content
ou match_parent
, car elles permettent à votre application de s'afficher correctement sur différentes tailles d'écran. Les types de mesures acceptés sont définis dans la ressource de mise en page.
Position de la mise en page
Une vue présente une géométrie rectangulaire. Elle possède un lieu, exprimé par une paire de coordonnées gauche et en haut, et deux dimensions, exprimées par une largeur et une hauteur. L'unité utilisée 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()
.
Le premier 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 20, cela signifie que la vue se trouve à 20 pixels à droite du bord gauche de son parent direct.
En outre, 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 à l'aide de la largeur et de la hauteur. Une vue a 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 de la vue dans son élément 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 (largeur de dessin) et drawing height (hauteur de dessin). 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, mais ce n'est pas obligatoire, différer de la largeur et de la hauteur mesurées. 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 une marge intérieure pour décaler le contenu de la vue d'un nombre spécifique de pixels. Par exemple, une marge intérieure gauche de deux pousse le contenu de la vue de deux pixels vers la droite du bord gauche. Vous pouvez définir une marge intérieure à l'aide de la méthode setPadding(int, int, int, int)
, puis 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. Toutefois, les groupes de vues acceptent les marges. Pour en savoir plus, consultez ViewGroup
et ViewGroup.MarginLayoutParams
.
Pour en savoir plus sur les dimensions, consultez la section Dimension.
En plus de définir des marges et des 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 que la marge et le remplissage sont appliqués. Des marges et une marge intérieure uniformes sont appliquées tout autour de TextView
, et Button
montre comment les appliquer indépendamment aux différents bords.
Mises en page courantes
Chaque sous-classe de la classe ViewGroup
fournit un moyen unique d'afficher les vues que vous imbriquez. Le type de mise en page le plus flexible, et celui qui fournit les meilleurs outils pour conserver une hiérarchie de mise en page superficielle, est ConstraintLayout
.
Vous trouverez ci-dessous quelques-uns des types de mise en page courants intégrés à la plate-forme Android.
![](https://developer.android.com/static/images/ui/linearlayout-small.png?authuser=6&hl=fr)
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 les mises en page courantes possibles avec RecyclerView
et AdapterView
:
RecyclerView
offre plus de possibilités et permet de créer un gestionnaire de mise en page personnalisé.
Remplir une vue d'adaptateur avec des données
Vous pouvez renseigner un élément AdapterView
tel que ListView
ou GridView
en liant l'instance AdapterView
à un élément Adapter
, qui récupère des données à partir d'une source externe et crée un élément View
qui représente chaque entrée de données.
Android fournit plusieurs sous-classes de Adapter
utiles pour récupérer différents types de données et créer des vues pour une AdapterView
. Les deux adaptateurs les plus courants sont les suivants:
ArrayAdapter
- Utilisez cet adaptateur lorsque votre source de données est un tableau. Par défaut,
ArrayAdapter
cré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 souhaitez afficher un tableau de chaînes 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 une valeur
TextView
pour chaque chaîne du tableau - Le 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. Pour créer une vue pour chaque élément autre qu'un élémentTextView
(par exemple, si vous souhaitez obtenir unImageView
pour chaque élément de tableau), étendez la classeArrayAdapter
et ignorezgetView()
afin de renvoyer le type d'affichage 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 deCursor
et les colonnes deCursor
que vous souhaitez insérer dans les vues de la mise en page souhaitée. Par exemple, si vous souhaitez créer une liste de noms et de numéros de téléphone de personnes, vous pouvez effectuer une requête qui renvoie unCursor
contenant 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 deCursor
à 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, l'élémentCursor
contenant les résultats et les deux tableaux suivants: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);
SimpleCursorAdapter
crée ensuite une vue pour chaque ligne deCursor
à l'aide de la mise en page fournie en insérant chaque élémentfromColumns
dans la vuetoViews
correspondante.
Si, au cours du cycle de vie de votre application, vous modifiez les données sous-jacentes lues par votre adaptateur, appelez notifyDataSetChanged()
.
Cela informe la vue associée que les données ont été modifiées, et qu'elle s'actualise.
Gérer les événements de clic
Vous pouvez répondre aux événements de clic sur chaque élément d'une AdapterView
en implémentant l'interface AdapterView.OnItemClickListener
. Par 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.