Pour l'instant, la racine de tous nos layouts a toujours été la même, ce qui fait que toutes nos applications avaient exactement le même squelette ! Mais il vous suffit de regarder n'importe quelle application Android pour réaliser que toutes les vues ne sont pas forcément organisées comme cela et qu'il existe une très grande variété d'architectures différentes. C'est pourquoi nous allons maintenant étudier les différents layouts, afin d'apprendre à placer nos vues comme nous le désirons. Nous pourrons ainsi concevoir une application plus attractive, plus esthétique et plus ergonomique !
- LinearLayout : placer les éléments sur une ligne
- RelativeLayout : placer les éléments les uns en fonction des autres
- TableLayout : placer les éléments comme dans un tableau
- FrameLayout : un layout un peu spécial
- ScrollView : faire défiler le contenu d'une vue
LinearLayout : placer les éléments sur une ligne
Comme son nom l'indique, ce layout se charge de mettre les vues sur une même ligne, selon une certaine orientation. L'attribut pour préciser cette orientation est android:orientation
. On peut lui donner deux valeurs :
vertical
pour que les composants soient placés de haut en bas (en colonne) ;horizontal
pour que les composants soient placés de gauche à droite (en ligne).
On va faire quelques expériences pour s'amuser !
Premier exemple
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <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/premier" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Premier bouton" /> <Button android:id="@+id/second" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Second bouton" /> </LinearLayout> |
Le rendu de ce code se trouve à la figure suivante.
- Le
LinearLayout
est vertical et prend toute la place de son parent (vous savez, l'invisible qui prend toute la place dans l'écran). - Le premier bouton prend toute la place dans le parent en largeur et uniquement la taille nécessaire en hauteur (la taille du texte, donc !).
- Le second bouton fait de même.
Deuxième exemple
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <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/premier" android:layout_width="wrap_content" android:layout_height="fill_parent" android:text="Premier bouton" /> <Button android:id="@+id/second" android:layout_width="wrap_content" android:layout_height="fill_parent" android:text="Second bouton" /> </LinearLayout> |
Le rendu de ce code se trouve à la figure suivante.
- Le
LinearLayout
est vertical et prend toute la place de son parent. - Le premier bouton prend toute la place de son parent en hauteur et uniquement la taille nécessaire en largeur.
- Comme le premier bouton prend toute la place, alors le pauvre second bouton se fait écraser. C'est pour cela qu'on ne le voit pas.
Troisième exemple
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" > <Button android:id="@+id/premier" android:layout_width="wrap_content" android:layout_height="fill_parent" android:text="Premier bouton" /> <Button android:id="@+id/second" android:layout_width="wrap_content" android:layout_height="fill_parent" android:text="Second bouton" /> </LinearLayout> |
Le rendu de ce code se trouve à la figure suivante.
- Le
LinearLayout
est vertical et prend toute la place en largeur mais uniquement la taille nécessaire en hauteur : dans ce cas précis, la taille nécessaire sera calculée en fonction de la taille des enfants. - Le premier bouton prend toute la place possible dans le parent. Comme le parent prend le moins de place possible, il doit faire de même.
- Le second bouton fait de même.
Quatrième exemple
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/premier" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Premier bouton" /> <Button android:id="@+id/second" android:layout_width="wrap_content" android:layout_height="fill_parent" android:text="Second bouton" /> </LinearLayout> |
Le rendu de ce code se trouve à la figure suivante.
- Le
LinearLayout
est horizontal et prend toute la place de son parent. - Le premier bouton prend uniquement la place nécessaire.
- Le second bouton prend uniquement la place nécessaire en longueur et s'étend jusqu'aux bords du parent en hauteur.
Vous remarquerez que l'espace est toujours divisé entre les deux boutons, soit de manière égale, soit un bouton écrase complètement l'autre. Et si on voulait que le bouton de droite prenne deux fois plus de place que celui de gauche par exemple ?
Pour cela, il faut attribuer un poids au composant. Ce poids peut être défini grâce à l'attribut android:layout_weight
. Pour faire en sorte que le bouton de droite prenne deux fois plus de place, on peut lui mettre android:layout_weight="1"
et mettre au bouton de gauche android:layout_weight="2"
. C'est alors le composant qui a la plus faible pondération qui a la priorité.
Et si, dans l'exemple précédent où un bouton en écrasait un autre, les deux boutons avaient eu un poids identique, par exemple android:layout_weight="1"
pour les deux, ils auraient eu la même priorité et auraient pris la même place. Par défaut, ce poids est à 0.
Une astuce que j'utilise souvent consiste à faire en sorte que la somme des poids dans un même layout fasse 100. C'est une manière plus évidente pour répartir les poids.
Dernier attribut particulier pour les widgets de ce layout, android:layout_gravity
, qu'il ne faut pas confondre avec android:gravity
. android:layout_gravity
vous permet de déterminer comment se placera la vue dans le parent, alors que android:gravity
vous permet de déterminer comment se placera le contenu de la vue à l'intérieur même de la vue (par exemple, comment se placera le texte dans un TextView
? Au centre, en haut, à gauche ?).
Vous prendrez bien un petit exemple pour illustrer ces trois concepts ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/bouton1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_weight="40" android:text="Bouton 1" /> <Button android:id="@+id/bouton2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_weight="20" android:gravity="bottom|right" android:text="Bouton 2" /> <Button android:id="@+id/bouton3" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:layout_weight="40" android:text="Bouton 3" /> </LinearLayout> |
Le rendu de ce code se trouve à la figure suivante.
Comme le bouton 2 a un poids deux fois inférieur aux boutons 1 et 3, alors il prend deux fois plus de place qu'eux. De plus, chaque bouton possède un attribut android:layout_gravity
afin de que l'on détermine sa position dans le layout. Le deuxième bouton présente aussi l'attribut android:gravity
, qui est un attribut de TextView
et non layout
, de façon à mettre le texte en bas (bottom
) à droite (right
).
Calcul de l'IMC - Partie 3.1
Énoncé
Récupérez le code de votre application de calcul de l'IMC et modifiez le layout pour obtenir quelque chose ressemblant à la figure suivante.
Les EditText
prennent le plus de place possible, mais comme ils ont un poids plus fort que les TextView
, ils n'ont pas la priorité.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Poids : " android:textStyle="bold" android:textColor="#FF0000" android:gravity="center" /> <EditText android:id="@+id/poids" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="Poids" android:inputType="numberDecimal" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Taille : " android:textStyle="bold" android:textColor="#FF0000" android:gravity="center" /> <EditText android:id="@+id/taille" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="Taille" android:inputType="numberDecimal" android:layout_weight="1" /> </LinearLayout> <RadioGroup android:id="@+id/group" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checkedButton="@+id/radio2" android:orientation="horizontal" > <RadioButton android:id="@+id/radio1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Mètre" /> <RadioButton android:id="@+id/radio2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Centimètre" /> </RadioGroup> <CheckBox android:id="@+id/mega" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Mega fonction !" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:id="@+id/calcul" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Calculer l'IMC" android:layout_weight="1" android:layout_marginLeft="25dip" android:layout_marginRight="25dip" /> <Button android:id="@+id/raz" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="RAZ" android:layout_weight="1" android:layout_marginLeft="25dip" android:layout_marginRight="25dip" /> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Résultat:" /> <TextView android:id="@+id/result" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="Vous devez cliquer sur le bouton « Calculer l'IMC » pour obtenir un résultat." /> </LinearLayout> |
De manière générale, on évite d'empiler les LinearLayout
(avoir un LinearLayout
dans un LinearLayout
, dans un LinearLayout
, etc.), c'est mauvais pour les performances d'une application.
RelativeLayout : placer les éléments les uns en fonction des autres
De manière totalement différente, ce layout propose plutôt de placer les composants les uns par rapport aux autres. Il est même possible de les placer par rapport au RelativeLayout
parent.
Si on veut par exemple placer une vue au centre d'un RelativeLayout
, on peut passer à cette vue l'attribut android:layout_centerInParent="true"
. Il est aussi possible d'utiliser android:layout_centerHorizontal="true"
pour centrer, mais uniquement sur l'axe horizontal, de même avec android:layout_centerVertical="true"
pour centrer sur l'axe vertical.
Premier exemple
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Centré dans le parent" android:layout_centerInParent="true" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Centré verticalement" android:layout_centerVertical="true" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Centré horizontalement" android:layout_centerHorizontal="true" /> </RelativeLayout> |
Le rendu de ce code se trouve à la figure suivante.
On observe ici une différence majeure avec le LinearLayout
: il est possible d'empiler les vues. Ainsi, le TextView
centré verticalement s’entremêle avec celui centré verticalement et horizontalement.
Il existe d'autres contrôles pour situer une vue par rapport à un RelativeLayout
. On peut utiliser :
android:layout_alignParentBottom="true"
pour aligner le plancher d'une vue au plancher duRelativeLayout
;android:layout_alignParentTop="true"
pour coller le plafond d'une vue au plafond duRelativeLayout
;android:layout_alignParentLeft="true"
pour coller le bord gauche d'une vue avec le bord gauche duRelativeLayout
;android:layout_alignParentRight="true"
pour coller le bord droit d'une vue avec le bord droit duRelativeLayout
.
Deuxième exemple
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="En haut !" android:layout_alignParentTop="true" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="En bas !" android:layout_alignParentBottom="true" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="A gauche !" android:layout_alignParentLeft="true" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="A droite !" android:layout_alignParentRight="true" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Ces soirées là !" android:layout_centerInParent="true" /> </RelativeLayout> |
Le rendu de ce code se trouve à la figure suivante.
On remarque tout de suite que les TextView
censés se situer à gauche et en haut s'entremêlent, mais c'est logique puisque par défaut une vue se place en haut à gauche dans un RelativeLayout
. Donc, quand on lui dit « Place-toi à gauche » ou « Place-toi en haut », c'est comme si on ne lui donnait pas d'instructions au final.
Enfin, il ne faut pas oublier que le principal intérêt de ce layout est de pouvoir placer les éléments les uns par rapport aux autres. Pour cela il existe deux catégories d'attributs :
- Ceux qui permettent de positionner deux bords opposés de deux vues différentes ensemble. On y trouve
android:layout_below
(pour aligner le plafond d'une vue sous le plancher d'une autre),android:layout_above
(pour aligner le plancher d'une vue sur le plafond d'une autre),android:layout_toRightOf
(pour aligner le bord gauche d'une vue au bord droit d'une autre) etandroid:layout_toLeftOf
(pour aligner le bord droit d'une vue au bord gauche d'une autre). - Ceux qui permettent de coller deux bords similaires ensemble. On trouve
android:layout_alignBottom
(pour aligner le plancher de la vue avec le plancher d'une autre),android:layout_alignTop
(pour aligner le plafond de la vue avec le plafond d'une autre),android:layout_alignLeft
(pour aligner le bord gauche d'une vue avec le bord gauche d'une autre) etandroid:layout_alignRight
(pour aligner le bord droit de la vue avec le bord droit d'une autre).
Troisième exemple
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/premier" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="[I] En haut à gauche par défaut" /> <TextView android:id="@+id/deuxieme" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="[II] En dessous de (I)" android:layout_below="@id/premier" /> <TextView android:id="@+id/troisieme" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="[III] En dessous et à droite de (I)" android:layout_below="@id/premier" android:layout_toRightOf="@id/premier" /> <TextView android:id="@+id/quatrieme" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="[IV] Au dessus de (V), bord gauche aligné avec le bord gauche de (II)" android:layout_above="@+id/cinquieme" android:layout_alignLeft ="@id/deuxieme" /> <TextView android:id="@+id/cinquieme" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="[V] En bas à gauche" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" /> </RelativeLayout> |
Le rendu de ce code se trouve à la figure suivante.
Je vous demande maintenant de regarder l'avant dernier TextView
, en particulier son attribut android:layout_above
. On ne fait pas référence au dernier TextView
comme aux autres, il faut préciser un +
! Eh oui, rappelez-vous, je vous avais dit il y a quelques chapitres déjà que, si nous voulions faire référence à une vue qui n'était définie que plus tard dans le fichier XML, alors il fallait ajouter un +
dans l'identifiant, sinon Android pensera qu'il s'agit d'une faute et non d'un identifiant qui sera déclaré après.
Calcul de l'IMC - Partie 3.2
Même chose pour un layout différent ! Moi, je vise le même résultat que précédemment.
Ma solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | <?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:id="@+id/textPoids" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Poids : " android:textStyle="bold" android:textColor="#FF0000" /> <EditText android:id="@+id/poids" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="Poids" android:inputType="numberDecimal" android:layout_toRightOf="@id/textPoids" android:layout_alignParentRight="true" /> <TextView android:id="@+id/textTaille" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Taille : " android:textStyle="bold" android:textColor="#FF0000" android:gravity="left" android:layout_below="@id/poids" /> <EditText android:id="@+id/taille" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="Taille" android:inputType="numberDecimal" android:layout_below="@id/poids" android:layout_toRightOf="@id/textTaille" android:layout_alignParentRight="true" /> <RadioGroup android:id="@+id/group" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checkedButton="@+id/radio2" android:orientation="horizontal" android:layout_below="@id/taille" > <RadioButton android:id="@+id/radio1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Mètre" /> <RadioButton android:id="@+id/radio2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Centimètre" /> </RadioGroup> <CheckBox android:id="@+id/mega" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Mega fonction !" android:layout_below="@id/group" /> <Button android:id="@+id/calcul" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Calculer l'IMC" android:layout_below="@id/mega" android:layout_marginLeft="25dip" /> <Button android:id="@+id/raz" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="RAZ" android:layout_below="@id/mega" android:layout_alignRight="@id/taille" android:layout_marginRight="25dip" /> <TextView android:id="@+id/resultPre" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Résultat:" android:layout_below="@id/calcul" /> <TextView android:id="@+id/result" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="Vous devez cliquer sur le bouton « Calculer l'IMC » pour obtenir un résultat." android:layout_below="@id/resultPre" /> </RelativeLayout> |
Le problème de ce layout, c'est qu'une petite modification dans l'interface graphique peut provoquer de grosses modifications dans tout le fichier XML, il faut donc savoir par avance très précisément ce qu'on veut faire.
Il s'agit du layout le plus compliqué à maîtriser, et pourtant le plus puissant tout en étant l'un des moins gourmands en ressources. Je vous encourage fortement à vous entraîner à l'utiliser.
TableLayout : placer les éléments comme dans un tableau
Dernier layout de base, il permet d'organiser les éléments en tableau, comme en HTML, mais sans les bordures. Voici un exemple d'utilisation de ce layout :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:stretchColumns="1"> <TextView android:text="Les items précédés d'un V ouvrent un sous-menu" /> <View android:layout_height="2dip" android:background="#FF909090" /> <TableRow> <TextView android:text="N'ouvre pas un sous-menu" android:layout_column="1" android:padding="3dip" /> <TextView android:text="Non !" android:gravity="right" android:padding="3dip" /> </TableRow> <TableRow> <TextView android:text="V" /> <TextView android:text="Ouvre un sous-menu" android:layout_column="1" android:padding="3dip" /> <TextView android:text="Là si !" android:gravity="right" android:padding="3dip" /> </TableRow> <View android:layout_height="2dip" android:background="#FF909090" /> <TableRow> <TextView android:text="V" /> <TextView android:text="Ouvre un sous-menu" android:padding="3dip" /> </TableRow> <View android:layout_height="2dip" android:background="#FF909090" /> <TableRow> <TextView android:layout_column="1" android:layout_span="2" android:text="Cet item s'étend sur deux colonnes, cool hein ?" android:padding="3dip" /> </TableRow> </TableLayout> |
Ce qui donne la figure suivante.
On observe tout d'abord qu'il est possible de mettre des vues directement dans le tableau, auquel cas elles prendront toute la place possible en longueur. En fait, elles s'étendront sur toutes les colonnes du tableau. Cependant, si on veut un contrôle plus complet ou avoir plusieurs éléments sur une même ligne, alors il faut passer par un objet <TableRow>
.
1 2 | <TextView android:text="Les items précédés d'un V ouvrent un sous-menu" /> |
Cet élément s'étend sur toute la ligne puisqu'il ne se trouve pas dans un <TableRow>
1 2 3 | <View android:layout_height="2dip" android:background="#FF909090" /> |
Moyen efficace pour dessiner un séparateur — n'essayez pas de le faire en dehors d'un <TableLayout>
ou votre application plantera.
Une ligne est composée de cellules. Chaque cellule peut contenir une vue, ou être vide. La taille du tableau en colonnes est celle de la ligne qui contient le plus de cellules. Dans notre exemple, nous avons trois colonnes pour tout le tableau, puisque la ligne avec le plus cellules est celle qui contient « V » et se termine par « Là si ! ».
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <TableRow> <TextView android:text="V" /> <TextView android:text="Ouvre un sous-menu" android:layout_column="1" android:padding="3dip" /> <TextView android:text="Là si !" android:gravity="right" android:padding="3dip" /> </TableRow> |
Cette ligne a trois éléments, c'est la plus longue du tableau, ce dernier est donc constitué de trois colonnes.
Il est possible de choisir dans quelle colonne se situe un item avec l'attribut android:layout_column
. Attention, l'index des colonnes commence à 0. Dans notre exemple, le dernier item se place directement à la deuxième colonne grâce à android:layout_column="1"
.
1 2 3 4 5 6 7 8 9 10 11 12 | <TableRow> <TextView android:text="N'ouvre pas un sous-menu" android:layout_column="1" android:padding="3dip" /> <TextView android:text="Non !" android:gravity="right" android:padding="3dip" /> </TableRow> |
On veut laisser vide l'espace pour la première colonne, on place alors les deux TextView
dans les colonnes 1 et 2.
La taille d'une cellule dépend de la cellule la plus large sur une même colonne. Dans notre exemple, la seconde colonne fait la largeur de la cellule qui contient le texte « N'ouvre pas un sous-menu », puisqu'il se trouve dans la deuxième colonne et qu'il n'y a pas d'autres éléments dans cette colonne qui soit plus grand.
Enfin, il est possible d'étendre un item sur plusieurs colonnes à l'aide de l'attribut android:layout_span
. Dans notre exemple, le dernier item s'étend de la deuxième colonne à la troisième. Il est possible de faire de même sur les lignes avec l'attribut android:layout_column
.
1 2 3 4 5 6 7 8 | <TableRow> <TextView android:layout_column="1" android:layout_span="2" android:text="Cet item s'étend sur deux colonnes, cool hein ?" android:padding="3dip" /> </TableRow> |
Ce TextView
débute à la deuxième colonne et s'étend sur deux colonnes, donc jusqu'à la troisième.
Sur le nœud TableLayout
, on peut jouer avec trois attributs (attention, les rangs débutent à 0) :
android:stretchColumns
pour que la longueur de tous les éléments de cette colonne passe enfill_parent
, donc pour prendre le plus de place possible. Il faut préciser le rang de la colonne à cibler, ou plusieurs rangs séparés par des virgules.android:shrinkColumns
pour que la longueur de tous les éléments de cette colonne passe enwrap_content
, donc pour prendre le moins de place possible. Il faut préciser le rang de la colonne à cibler, ou plusieurs rangs séparés par des virgules.android:collapseColumns
pour faire purement et simplement disparaître des colonnes du tableau. Il faut préciser le rang de la colonne à cibler, ou plusieurs rangs séparés par des virgules.
Calcul de l'IMC - Partie 3.3
Énoncé
Réitérons l'expérience, essayez encore une fois d'obtenir le même rendu, mais cette fois avec un TableLayout
. L'exercice est intéressant puisqu'on n'est pas vraiment en présence d'un tableau, il va donc falloir réfléchir beaucoup et exploiter au maximum vos connaissances pour obtenir un rendu acceptable.
Ma solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:stretchColumns="1"> <TableRow> <TextView android:text="Poids : " android:textStyle="bold" android:textColor="#FF0000" android:gravity="center" /> <EditText android:id="@+id/poids" android:hint="Poids" android:inputType="numberDecimal" android:layout_span="2" /> </TableRow> <TableRow> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Taille : " android:textStyle="bold" android:textColor="#FF0000" android:gravity="center" /> <EditText android:id="@+id/taille" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="Taille" android:inputType="numberDecimal" android:layout_span="2" /> </TableRow> <RadioGroup android:id="@+id/group" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checkedButton="@+id/radio2" android:orientation="horizontal"> <RadioButton android:id="@+id/radio1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Mètre" /> <RadioButton android:id="@+id/radio2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Centimètre" /> </RadioGroup> <CheckBox android:id="@+id/mega" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Mega fonction !" /> <TableRow> <Button android:id="@+id/calcul" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Calculer l'IMC" /> <Button android:id="@+id/raz" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="RAZ" android:layout_column="2" /> </TableRow> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Résultat:" /> <TextView android:id="@+id/result" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="Vous devez cliquer sur le bouton « Calculer l'IMC » pour obtenir un résultat." /> </TableLayout> |
FrameLayout : un layout un peu spécial
Ce layout est plutôt utilisé pour afficher une unique vue. Il peut sembler inutile comme ça, mais ne l'est pas du tout ! Il n'est destiné à afficher qu'un élément, mais il est possible d'en mettre plusieurs dedans puisqu'il s'agit d'un ViewGroup
. Si par exemple vous souhaitez faire un album photo, il vous suffit de mettre plusieurs éléments dans le FrameLayout
et de ne laisser qu'une seule photo visible, en laissant les autres invisibles grâce à l'attribut android:visibility
(cet attribut est disponible pour toutes les vues). Pareil pour un lecteur de PDF, il suffit d'empiler toutes les pages dans le FrameLayout
et de n'afficher que la page actuelle, celle du dessus de la pile, à l'utilisateur. Cet attribut peut prendre trois valeurs :
visible
(View.VISIBLE
), la valeur par défaut.invisible
(View.INVISIBLE
) n'affiche rien, mais est pris en compte pour l'affichage du layout niveau spatial (on lui réserve de la place).gone
(View.GONE
) n'affiche rien et ne prend pas de place, un peu comme s'il n'était pas là.
L'équivalent Java de cet attribut est public void setVisibility (int)
avec comme paramètre une des valeurs entre parenthèses dans la liste ci-dessus. Quand il y a plusieurs éléments dans un FrameLayout
, celui-ci les empile les uns au-dessus des autres, le premier élément du XML se trouvant en dernière position et le dernier ajouté tout au-dessus.
ScrollView : faire défiler le contenu d'une vue
Ne vous laissez pas bernez par son nom, cette vue est bel et bien un layout. Elle est par ailleurs un peu particulière puisqu'elle fait juste en sorte d'ajouter une barre de défilement verticale à un autre layout. En effet, si le contenu de votre layout dépasse la taille de l'écran, une partie du contenu sera invisible à l'utilisateur. De façon à rendre ce contenu visible, on peut préciser que la vue est englobée dans une ScrollView
, et une barre de défilement s'ajoutera automatiquement.
Ce layout hérite de FrameLayout
, par conséquent il vaut mieux envisager de ne mettre qu'une seule vue dedans.
Il s'utilise en général avec LinearLayout
, mais peut être utilisé avec tous les layouts… ou bien des widgets ! Par exemple :
1 2 3 4 5 6 7 8 9 | <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content"> <LinearLayout> <!-- contenu du layout --> </LinearLayout> </ScrollView> |
Attention cependant, il ne faut pas mettre de widgets qui peuvent déjà défiler dans une ScrollView
, sinon il y aura conflit entre les deux contrôleurs et le résultat sera médiocre. Nous n'avons pas encore vu de widgets de ce type, mais cela ne saurait tarder.
LinearLayout
permet d'afficher plusieurs vues sur une même ligne de manière horizontale ou verticale. Il est possible d'attribuer un poids aux vues pour effectuer des placements précis.RelativeLayout
permet d'afficher des vues les unes en fonction des autres.TableLayout
permet d'organiser les éléments en tableau.FrameLayout
permet d'afficher une vue à l'écran ou d'en superposer plusieurs les unes au-dessus des autres.ScrollView
permet de rendre « scrollable » la vue qu'elle contient. Attention de ne lui donner qu'un fils et de ne pas fournir des vues déjà « scrollable » sinon il y aura des conflits.