Maintenant que vous avez parfaitement compris ce qu'étaient les ressources, pourquoi et comment les utiliser, je vous propose de voir… comment les créer. Il existe une grande variété ressources différences, c'est pourquoi on ne les verra pas toutes. Je vous présenterai ici uniquement les plus utiles et plus compliquées à utiliser.
Un dernier conseil avant d'entrer dans le vif du sujet : créez le plus de ressources possible, dès que vous le pouvez. Ainsi, vos applications seront plus flexibles, et le développement sera plus évident.
- Aspect général des fichiers de ressources
- Les chaînes de caractères
- Les drawables
- Les styles
- Les animations
Aspect général des fichiers de ressources
Nous allons voir comment sont constitués les fichiers de ressources qui contiennent des values (je les appellerai « données » désormais). C'est encore une fois un fichier XML, mais qui revêt cette forme-ci :
1 2 3 4 | <?xml version="1.0" encoding="utf-8"?> <resources> … </resources> |
Afin d'avoir un petit aperçu de ce à quoi elles peuvent ressembler, on va d'abord observer les fichiers que crée Android à la création d'un nouveau projet. Double-cliquez sur le fichier res/values/strings.xml
pour ouvrir une nouvelle fenêtre (voir figure suivante).
On retrouve à gauche toutes les ressources qui sont contenues dans ce fichier. Là il y en a deux, c'est plutôt facile de s'y retrouver, mais imaginez un gros projet avec une cinquantaine voire une centaine de données, vous risquez de vite vous y perdre. Si vous voulez éviter ce type de désagréments, vous pouvez envisager deux manières de vous organiser :
- Réunir les données d'un même type pour une activité dans un seul fichier. Par exemple
strings.xml
pour toutes les chaines de caractères. Le problème est qu'il vous faudra créer beaucoup de fichiers, ce qui peut être long. - Ou alors mettre toutes les données d'une activité dans un fichier, ce qui demande moins de travail, mais nécessite une meilleure organisation afin de pouvoir s'y retrouver.
N'oubliez pas qu'Android est capable de retrouver automatiquement des ressources parce qu'elles se situent dans un fichier précis à un emplacement précis. Ainsi, quelle que soit l'organisation pour laquelle vous optez, il faudra la répercuter à tous les répertoires values
, tous différenciés par des quantificateurs, pour que les données se retrouvent dans des fichiers au nom identique mais dans des répertoires différents.
Si vous souhaitez opter pour la seconde organisation, alors le meilleur moyen de s'y retrouver est de savoir trier les différentes ressources à l'aide du menu qui se trouve en haut de la fenêtre. Il vous permet de filtrer la liste des données en fonction de leur type. Voici la signification de tous les boutons :
- : Afficher uniquement les chaînes de caractères (
String
) - : Afficher uniquement les couleurs (
Color
) - : Afficher uniquement les dimensions (
Dimension
) - : Afficher uniquement les drawables (
Drawable
) - : Afficher uniquement les styles et thèmes (
Style
) - : Afficher uniquement les éléments qui appartiennent à un ensemble (à un tableau par exemple) (
Item
) - : Afficher uniquement les tableaux de chaînes de caractères (
String Array
) - : Afficher uniquement les tableaux d'entiers (
Int Array
) - : Ranger la liste dans l'ordre alphabétique du nom de la donnée. Un second clic range dans l'ordre alphabétique inverse
De plus, le menu du milieu (voir figure suivante) vous permet de créer ou supprimer des données.
- Le bouton
Add…
permet d'ajouter une nouvelle donnée. - Le bouton
Remove…
permet de supprimer une donnée. - Le bouton
Up
permet d'augmenter d'un cran la position de la donnée dans le tableau central. - Le bouton
Down
permet de diminuer d'un cran la position de la donnée dans le tableau central.
Personnellement, je n'utilise cette fenêtre que pour avoir un aperçu rapide de mes données. Cependant, dès qu'il me faut effectuer des manipulations, je préfère utiliser l'éditeur XML. D'ailleurs je ne vous apprendrai ici qu'à travailler avec un fichier XML, de manière à ce que vous ne soyez pas totalement déboussolés si vous souhaitiez utiliser une autre extension que l'ADT. Vous pouvez naviguer entre les deux interfaces à l'aide des deux boutons en bas de la fenêtre, visibles à la figure suivante.
Référence à une ressource
Nous avons déjà vu que quand une ressource avait un identifiant, Android s'occupait d'ajouter au fichier R.java
une référence à l'identifiant de cette ressource, de façon à ce que nous puissions la récupérer en l'inflatant. La syntaxe de la référence était :
1 | R.type_de_ressource.nom_de_la_ressource |
Ce que je ne vous ai pas dit, c'est qu'il était aussi possible d'y accéder en XML. Ce n'est pas tellement plus compliqué qu'en Java puisqu'il suffit de respecter la syntaxe suivante :
1 | @type_de_ressource/nom_de_la_ressource |
Par exemple pour une chaîne de caractères qui s'appellerait salut
, on y ferait référence en Java à l'aide de R.strings.salut
et en XML avec @string/salut
.
Enfin, si la ressource à laquelle on essaie d'accéder est une ressource fournie par Android dans son SDK, il suffit de respecter la syntaxe Android.R.type_de_ressource.nom_de_la_ressource
en Java et @android:type_de_ressource/nom_de_la_ressource
en XML.
Les chaînes de caractères
Vous connaissez les chaînes de caractères, c'est le mot compliqué pour désigner un texte. La syntaxe est évidente à maîtriser, par exemple si nous voulions créer une chaîne de caractères de nom « nomDeLExemple » et de valeur Texte de la chaîne qui s'appelle "nomDeLExemple"
:
1 | <string name="nomDeLExemple">Texte de la chaîne qui s appelle nomDeLExemple</string> |
Et ils ont disparu où, les guillemets et l'apostrophe ?
Commençons par l'évidence, s'il n'y a ni espace, ni apostrophe dans le nom, c'est parce qu'il s'agit du nom d'une variable comme nous l'avons vu précédemment, par conséquent il faut respecter les règles de nommage d'une variable standard.
Pour ce qui est du texte, il est interdit d'insérer des apostrophes ou des guillemets. Sinon, comment Android peut-il détecter que vous avez fini d'écrire une phrase ? Afin de contourner cette limitation, vous pouvez très bien échapper les caractères gênants, c'est-à-dire les faire précéder d'un antislash ().
1 | <string name="nomDeLExemple">Texte de la chaîne qui s\'appelle \"nomDeLExemple\"</string> |
Vous pouvez aussi encadrer votre chaîne de guillemets afin de ne pas avoir à échapper les apostrophes ; en revanche vous aurez toujours à échapper les guillemets.
1 | <string name="nomDeLExemple">"Texte de la chaîne qui s'appelle \"nomDeLExemple\""</string> |
Application
Je vous propose de créer un bouton et de lui associer une chaîne de caractères qui contient des balises HTML (<b>
, <u>
et <i>
) ainsi que des guillemets et des apostrophes. Si vous ne connaissez pas de balises HTML, vous allez créer la chaîne suivante : « Vous connaissez l'histoire de <b>"Tom Sawyer"</b> ?
». Les balises <b></b>
vous permettent de mettre du texte en gras.
Instructions
- On peut convertir notre
String
enSpanned
.Spanned
est une classe particulière qui représente les chaînes de caractères qui contiennent des balises HTML et qui peut les interpréter pour les afficher comme le ferait un navigateur internet. Cette transformation se fait à l'aide de la méthode statiqueSpanned Html.fromHtml (String source)
. - On mettra ce
Spanned
comme texte sur le bouton avec la méthodevoid setText (CharSequence text)
.
Les caractères spéciaux < et > doivent être écrits en code HTML. Au lieu d'écrire < vous devez marquer «
et à la place de > il faut insérer »
. Si vous utilisez l'interface graphique pour la création de String
, il convertira automatiquement les caractères ! Mais il convertira aussi les guillemets en code HTML, ce qu'il ne devrait pas faire…
Ma correction
Le fichier strings.xml
:
1 2 3 4 5 6 | <?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, TroimsActivity!</string> <string name="histoire">Vous connaissez l\'histoire de <b>\"Tom Sawyer\"</b> ?</string> <string name="app_name">Troims</string> </resources> |
Et le code Java associé :
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 | import android.app.Activity; import android.os.Bundle; import android.text.Html; import android.text.Spanned; import android.widget.Button; public class StringExampleActivity extends Activity { Button button = null; String hist = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // On récupère notre ressource au format String hist = getResources().getString(R.string.histoire); // On le convertit en Spanned Spanned marked_up = Html.fromHtml(hist); button = new Button(this); // Et on attribue le Spanned au bouton button.setText(marked_up); setContentView(button); } } |
Formater des chaînes de caractères
Le problème avec nos chaînes de caractères en tant que ressources, c'est qu'elles sont statiques. Elles ne sont pas destinées à être modifiées et par conséquent elles ne peuvent pas s'adapter.
Imaginons une application qui salue quelqu'un, qui lui donne son âge, et qui s'adapte à la langue de l'utilisateur. Il faudrait qu'elle dise : « Bonjour Anaïs, vous avez 22 ans » en français et « Hello Anaïs, you are 22 » en anglais. Cette technique est par exemple utilisée dans le jeu Civilization IV pour traduire le texte en plusieurs langues. Pour indiquer dans une chaîne de caractères à quel endroit se situe la partie dynamique, on va utiliser un code. Dans l'exemple précédent, on pourrait avoir Bonjour %1$s, vous avez %2$d ans
en français et Hello %1$s, you are %2$d
en anglais. L'astuce est que la première partie du code correspond à une position dans une liste d'arguments (qu'il faudra fournir) et la seconde partie à un type de texte (int
, float
, string
, bool
, …). En d'autres termes, un code se décompose en deux parties :
%n
avec « n » étant un entier naturel (nombre sans virgule et supérieur à 0) qui sert à indiquer le rang de l'argument à insérer (%1
correspond au premier argument,%2
au deuxième argument, etc.) ;$x
, qui indique quel type d'information on veut ajouter ($s
pour une chaîne de caractères et$d
pour un entier — vous pourrez trouver la liste complète des possibilités sur cette page).
On va maintenant voir comment insérer les arguments. Il existe au moins deux manières de faire.
On peut le faire en récupérant la ressource :
1 2 3 | Resources res = getResources(); // Anaïs ira en %1 et 22 ira en %2 String chaine = res.getString(R.string.hello, "Anaïs", 22); |
Ou alors sur n'importe quelle chaîne avec une fonction statique de String
:
1 2 | // On n'est pas obligé de préciser la position puisqu'on n'a qu'un argument ! String iLike = String.format("J'aime les $s", "pâtes"); |
Application
C'est simple, je vais vous demander d'arriver au résultat visible à la figure suivante.
Ma solution
On aura besoin de deux fichiers strings.xml
: un dans le répertoire values
et un dans le répertoire values-en
qui contiendra le texte en anglais :
values/strings.xml
1 2 3 4 5 | <?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Bonjour %1$s, vous avez %2$d ans.</string> <string name="app_name">Deums</string> </resources> |
values-en/strings.xml
1 2 3 4 5 | <?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello %1$s, you are %2$d.</string> <string name="app_name">Deums</string> </resources> |
De plus on va donner un identifiant à notre TextView
pour récupérer la chaîne :
1 2 3 4 5 6 7 8 9 10 11 12 | <?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" > <TextView android:id="@+id/vue" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> |
Et enfin, on va récupérer notre TextView
et afficher le texte correct pour une femme s’appelant Anaïs et qui aurait 22 ans :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import android.app.Activity; import android.content.res.Resources; import android.os.Bundle; import android.widget.TextView; public class DeumsActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Resources res = getResources(); // Anaïs se mettra dans %1 et 22 ira dans %2, mais le reste changera en fonction de la langue du terminal ! String chaine = res.getString(R.string.hello, "Anaïs", 22); TextView vue = (TextView)findViewById(R.id.vue); vue.setText(chaine); } } |
Et voilà, en fonction de la langue de l'émulateur, le texte sera différent !
Les drawables
La dénomination « drawable » rassemble tous les fichiers « dessinables » (oui, ce mot n'existe pas en français, mais « drawable » n'existe pas non plus en anglais après tout ), c'est-à-dire les dessins ou les images. Je ne parlerai que des images puisque ce sont les drawables les plus utilisés et les plus indispensables.
Les images matricielles
Android supporte trois types d'images : les PNG, les GIF et les JPEG. Sachez que ces trois formats n'ont pas les mêmes usages :
- Les GIF sont peu recommandés. On les utilise sur internet pour les images de moindre qualité ou les petites animations. On va donc les éviter le plus souvent.
- Les JPEG sont surtout utilisés en photographie ou pour les images dont on veut conserver la haute qualité. Ce format ne gère pas la transparence, donc toutes vos images seront rectangulaires.
- Les PNG sont un bon compromis entre compression et qualité d'image. De plus, ils gèrent la transparence. Si le choix se présente, optez pour ce format-là.
Il n'y a rien de plus simple que d'ajouter une image dans les ressources, puisqu'il suffit de faire glisser le fichier à l'emplacement voulu dans Eclipse (ou mettre le fichier dans le répertoire voulu dans les sources de votre projet), comme à la figure suivante, et le drawable sera créé automatiquement.
Le nom du fichier déterminera l'identifiant du drawable, et il pourra contenir toutes les lettres minuscules, tous les chiffres et des underscores ( _ ), mais attention, pas de majuscules. Puis, on pourra récupérer le drawable à l'aide de R.drawable.nom_du_fichier_sans_l_extension
.
Les images extensibles
Utiliser une image permet d'agrémenter son application, mais, si on veut qu'elle soit de qualité pour tous les écrans, il faudrait une image pour chaque résolution, ce qui est long. La solution la plus pratique serait une image qui s'étire sans jamais perdre en qualité ! Dans les faits, c'est difficile à obtenir, mais certaines images sont assez simples pour qu'Android puisse déterminer comment étirer l'image en perdant le moins de qualité possible. Je fais ici référence à la technique 9-Patch. Un exemple sera plus parlant qu'un long discours : on va utiliser l'image visible à la figure suivante, qui est aimablement prêtée par ce grand monsieur, qui nous autorise à utiliser ses images, même pour des projets professionnels, un grand merci à lui.
Cette image ne paye pas de mine, mais elle pourra être étendue jusqu'à former une image immense sans pour autant être toute pixellisée. L'astuce consiste à indiquer quelles parties de l'image peuvent être étendues, et le SDK d'Android contient un outil pour vous aider dans votre démarche. Par rapport à l'endroit où vous avez installé le SDK, il se trouve dans \Android\tools\draw9patch.bat
. Vous pouvez directement glisser l'image dans l'application pour l'ouvrir ou bien aller dans File > Open 9-patch…
(voir figure suivante).
Ce logiciel contient trois zones différentes :
- La zone de gauche représente l'image et c'est dans cette zone que vous pouvez dessiner. Si, si, essayez de dessiner un gros cœur au milieu de l'image. Je vous ai eus ! Vous ne pouvez en fait dessiner que sur la partie la plus extérieure de l'image, la bordure qui fait un pixel de largeur et qui entoure l'image.
- Celle de droite est un aperçu de l'image élargie de plusieurs façons. Vous pouvez voir qu'actuellement les images agrandies sont grossières, les coins déformés et de gros pixels sont visibles.
- Et en bas on trouve plusieurs outils pour vous aider dans votre tâche.
Si vous passez votre curseur à l'intérieur de l'image, un filtre rouge s'interposera de façon à vous indiquer que vous ne devez pas dessiner à cet endroit (mais vous pouvez désactiver ce filtre avec l'option Show lock
). En effet, l'espèce de quadrillage à côté de votre image indique les zones de transparence, celles qui ne contiennent pas de dessin. Votre rôle sera d'indiquer quels bords de l'image sont extensibles et dans quelle zone de l'objet on pourra insérer du contenu. Pour indiquer les bords extensibles on va tracer un trait d'une largeur d'un pixel sur les bords haut et gauche de l'image, alors que des traits sur les bords bas et droite déterminent où peut se placer le contenu. Par exemple pour cette image, on pourrait avoir (il n'y a pas qu'une façon de faire, faites en fonction de ce que vous souhaitez obtenir) le résultat visible à la figure suivante.
Vous voyez la différence ? Les images étirées montrent beaucoup moins de pixels et les transitions entre les couleurs sont bien plus esthétiques ! Enfin pour ajouter cette image à votre projet, il vous suffit de l'enregistrer au format .9.png
, puis de l'ajouter à votre projet comme un drawable standard.
L'image suivante vous montre plus clairement à quoi correspondent les bords :
Les commandes
- Le slider
Zoom
vous permet de vous rapprocher ou vous éloigner de l'image originale. - Le slider
Patch scale
vous permet de vous rapprocher ou vous éloigner des agrandissements. Show patches
montre les zones qui peuvent être étendue dans la zone de dessin.Show content
vous montre la zone où vous pourrez insérer du contenu (image ou texte) dans Android.- Enfin, vous voyez un bouton en haut de la zone de dessin,
Show bad patches
, qui une fois coché vous montre les zones qui pourraient provoquer des désagréments une fois l'image agrandie ; l'objectif sera donc d'en avoir le moins possible (voire aucune).
Les styles
Souvent quand on fait une application, on adopte un certain parti pris en ce qui concerne la charte graphique. Par exemple, des tons plutôt clairs avec des boutons blancs qui font une taille de 20 pixels et dont la police du texte serait en cyan. Et pour dire qu'on veut que tous les boutons soient blancs, avec une taille de 20 pixels et le texte en cyan, il va falloir indiquer pour chaque bouton qu'on veut qu'il soit blanc, avec une taille de 20 pixels et le texte en cyan, ce qui est très vite un problème si on a beaucoup de boutons !
Afin d'éviter d'avoir à se répéter autant, il est possible de définir ce qu'on appelle un style. Un style est un ensemble de critères esthétiques dont l'objectif est de pouvoir définir plusieurs règles à différents éléments graphiques distincts. Ainsi, il est plus évident de créer un style « Boutons persos », qui précise que la cible est « blanche, avec une taille de 20 pixels et le texte en cyan » et d'indiquer à tous les boutons qu'on veut qu'ils soient des « Boutons persos ». Et si vous voulez mettre tous vos boutons en jaune, il suffit simplement de changer l'attribut blanc du style « Bouton persos » en jaune .
Les styles sont des values, on doit donc les définir au même endroit que les chaînes de caractères.
Voici la forme standard d'un style :
1 2 3 4 5 6 7 8 9 | <resources> <style name="nom_du_style" parent="nom_du_parent"> <item name="propriete_1">valeur_de_la_propriete_1</item> <item name="propriete_2">valeur_de_la_propriete_2</item> <item name="propriete_3">valeur_de_la_propriete_3</item> … <item name="propriete_n">valeur_de_la_propriete_n</item> </style> </resources> |
Voici les règles à respecter :
- Comme d'habitude, on va définir un nom unique pour le style, puisqu'il y aura une variable pour y accéder.
- Il est possible d'ajouter des propriétés physiques à l'aide d'
<item>
. Le nom de l'<item>
correspond à un des attributs destinés auxVues
, qu'on a déjà étudiés. Par exemple pour changer la couleur d'un texte, on va utiliser l'attributandroid:textColor
. - Enfin, on peut faire hériter notre style d'un autre style — qu'il ait été défini par Android ou par vous-mêmes — et ainsi récupérer ou écraser les attributs d'un parent.
Le style suivant permet de mettre du texte en cyan :
1 2 3 | <style name="texte_cyan"> <item name="android:textColor">#00FFFF</item> </style> |
Les deux styles suivants héritent du style précédent en rajoutant d'autres attributs :
1 2 3 4 | <style name="texte_cyan_grand" parent="texte_cyan"> <!-- On récupère la couleur du texte définie par le parent --> <item name="android:textSize">20sp</item> </style> |
1 2 3 4 | <style name="texte_rouge_grand" parent="texte_cyan_grand"> <!-- On écrase la couleur du texte définie par le parent, mais on garde la taille --> <item name="android:textColor">#FF0000</item> </style> |
Il est possible de n'avoir qu'un seul parent pour un style, ce qui peut être très vite pénible, alors organisez-vous à l'avance !
Il est ensuite possible d'attribuer un style à une vue en XML avec l'attribut style="identifiant_du_style"
. Cependant, un style ne s'applique pas de manière dynamique en Java, il faut alors préciser le style à utiliser dans le constructeur. Regardez le constructeur d'une vue : public View (Context contexte, AttributeSet attrs)
. Le paramètre attrs
est facultatif, et c'est lui qui permet d'attribuer un style à une vue. Par exemple :
1 | Button bouton = new Button (this, R.style.texte_rouge_grand); |
Les animations
Pour donner un peu de dynamisme à notre interface graphique, on peut faire en sorte de bouger, faire tourner, agrandir ou faire disparaître une vue ou un ensemble de vues. Mais au préalable sachez qu'il est possible de placer un système de coordonnées sur notre écran de manière à pouvoir y situer les éléments. Comme à la figure suivante, l'axe qui va de gauche à droite s'appelle l'axe X et l'axe qui va de haut en bas s'appelle l'axe Y.
Voici quelques informations utiles :
- Sur l'axe X, plus on se déplace vers la droite, plus on s'éloigne de 0.
- Sur l'axe Y, plus on se déplace vers le bas, plus on s'éloigne de 0.
- Pour exprimer une coordonnée, on utilise la notation (X, Y).
- L'unité est le pixel.
- Le point en haut à gauche a pour coordonnées (0, 0).
- Le point en bas à droite a pour coordonnées (largeur de l'écran, hauteur de l'écran).
Définition en XML
Contrairement aux chaînes de caractères et aux styles, les animations ne sont pas des données mais des ressources indépendantes, comme l'étaient les drawables. Elles doivent être définies dans le répertoire res/anim/
.
Pour un widget
Il existe quatre animations de base qu'il est possible d'effectuer sur une vue (que ce soit un widget ou un layout !). Une animation est décrite par un état de départ pour une vue et un état d'arrivée : par exemple on part d'une vue visible pour qu'elle devienne invisible.
Transparence
<alpha>
permet de faire apparaître ou disparaître une vue.
android:fromAlpha
est la transparence de départ avec 0.0 pour une vue totalement transparente et 1.0 pour une vue totalement visible.android:toAlpha
est la transparence finale voulue avec 0.0 pour une vue totalement transparente et 1.0 pour une vue totalement visible.
Rotation
<rotate>
permet de faire tourner une vue autour d'un axe.
android:fromDegrees
est l'angle de départ.android:pivotX
est la coordonnée du centre de rotation sur l'axe X (en pourcentages par rapport à la gauche de la vue, par exemple 50% correspond au milieu de la vue et 100% au bord droit).android:pivotY
est la coordonnée du centre de rotation sur l'axe Y (en pourcentages par rapport au plafond de la vue).android:toDegrees
est l'angle voulu à la fin.
Taille
<scale>
permet d'agrandir ou de réduire une vue.
android:fromXScale
est la taille de départ sur l'axe X (1.0 pour la valeur actuelle).android:fromYScale
est la taille de départ sur l'axe Y (1.0 pour la valeur actuelle).android:pivotX
(identique à<rotate>
).android:pivotY
(identique à<rotate>
).android:toXScale
est la taille voulue sur l'axe X (1.0 pour la valeur de départ).android:toYScale
est la taille voulue sur l'axe Y (1.0 pour la valeur de départ).
Mouvement
<translate>
permet de faire subir une translation à une vue (mouvement rectiligne).
android:fromXDelta
est le point de départ sur l'axe X (en pourcentages).android:fromYDelta
est le point de départ sur l'axe Y (en pourcentages).android:toXDelta
est le point d'arrivée sur l'axe X (en pourcentages).android:toYDelta
est le point d'arrivée sur l'axe Y (en pourcentages).
Sachez qu'il est en plus possible de regrouper les animations en un ensemble et de définir un horaire de début et un horaire de fin. Le nœud qui représente cet ensemble est de type <set>
. Tous les attributs qui sont passés à ce nœud se répercuteront sur les animations qu'il contient. Par exemple :
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <scale android:fromXScale="1.0" android:fromYScale="1.0" android:toXScale="2.0" android:toYScale="0.5" android:pivotX="50%" android:pivotY="50%" /> <alpha android:fromAlpha="1.0" android:toAlpha="0.0" /> </set> |
android:pivotX="50%"
et android:pivotY="50%"
permettent de placer le centre d'application de l'animation au milieu de la vue.
Dans ce code, le scale
et l'alpha
se feront en même temps ; cependant notre objectif va être d'effectuer d'abord le scale
, et seulement après l'alpha
. Pour cela, on va dire au scale
qu'il démarrera exactement au lancement de l'animation, qu'il durera 0,3 seconde et on dira à l'alpha
de démarrer à partir de 0,3 seconde, juste après le scale
. Pour qu'une animation débute immédiatement, il ne faut rien faire, c'est la propriété par défaut. En revanche pour qu'elle dure 0,3 seconde, il faut utiliser l'attribut android:duration
qui prend comme valeur la durée en millisecondes (ça veut dire qu'il vous faut multiplier le temps en secondes par 1000). Enfin, pour définir à quel moment l'alpha
débute, c'est-à-dire avec quel retard, on utilise l'attribut android:startOffset
(toujours en millisecondes). Par exemple, pour que le scale
démarre immédiatement, dure 0,3 seconde et soit suivi par un alpha
qui dure 2 secondes, voici ce qu'on écrira :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <scale android:fromXScale="1.0" android:fromYScale="1.0" android:toXScale="2.0" android:toYScale="0.5" android:pivotX="50%" android:pivotY="50%" android:duration="300"/> <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:startOffset="300" android:duration="2000"/> </set> |
Un dernier détail. Une animation permet de donner du dynamisme à une vue, mais elle n'effectuera pas de changements réels sur l'animation : l'animation effectuera l'action, mais uniquement sur le plan visuel. Ainsi, si vous essayez ce code, Android affichera un mouvement, mais une fois l'animation finie, les vues redeviendront exactement comme elles étaient avant le début de l'animation. Heureusement, il est possible de demander à votre animation de changer les vues pour qu'elles correspondent à leur état final à la fin de l'animation. Il suffit de rajouter les deux attributs android:fillAfter="true"
et android:fillEnabled="true"
.
Enfin je ne vais pas abuser de votre patience, je comprendrais que vous ayez envie d'essayer votre nouveau joujou. Pour ce faire, c'est très simple, utilisez la classe AnimationUtils
.
1 2 3 4 | // On crée un utilitaire de configuration pour cette animation Animation animation = AnimationUtils.loadAnimation(contexte_dans_lequel_se_situe_la_vue, identifiant_de_l_animation); // On l'affecte au widget désiré, et on démarre l'animation le_widget.startAnimation(animation); |
Pour un layout
Si vous effectuez l'animation sur un layout, alors vous aurez une petite manipulation à faire. En fait, on peut très bien appliquer une animation normale à un layout avec la méthode que nous venons de voir, mais il se trouve qu'on voudra parfois faire en sorte que l'animation se propage parmi les enfants du layout pour donner un joli effet.
Tout d'abord, il vous faut créer un nouveau fichier XML, toujours dans le répertoire res/anim
, mais la racine de celui-ci sera un nœud de type <layoutAnimation>
(attention au « l » minuscule !). Ce nœud peut prendre trois attributs. Le plus important est android:animation
puisqu'il faut y mettre l'identifiant de l'animation qu'on veut passer au layout. On peut ensuite définir le délai de propagation de l'animation entre les enfants à l'aide de l'attribut android:delay
. Le mieux est d'utiliser un pourcentage, par exemple 100% pour attendre que l'animation soit finie ou 0% pour ne pas attendre. Enfin, on peut définir l'ordre dans lequel l'animation s'effectuera parmi les enfants avec android:animationOrder
, qui peut prendre les valeurs : normal
pour l'ordre dans lequel les vues ont été ajoutées au layout, reverse
pour l'ordre inverse et random
pour une distribution aléatoire entre les enfants.
On obtient alors :
1 2 3 4 5 6 | <?xml version="1.0" encoding="utf-8"?> <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:delay="10%" android:animationOrder="random" android:animation="@anim/animation_standard" /> |
Puis on peut l'utiliser dans le code Java avec :
1 2 | LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(contexte_dans_lequel_se_situe_la_vue, identifiant_de_l_animation); layout.setLayoutAnimation(animation); |
On aurait aussi pu passer l'animation directement au layout en XML avec l'attribut android:layoutAnimation="identifiant_de_l_animation"
.
Un dernier raffinement : l'interpolation
Nos animations sont super, mais il manque un petit quelque chose qui pourrait les rendre encore plus impressionnantes. Si vous testez les animations, vous verrez qu'elles sont constantes, elles ne montrent pas d'effets d'accélération ou de décélération par exemple. On va utiliser ce qu'on appelle un agent d'interpolation, c'est-à-dire une fonction mathématique qui va calculer dans quel état doit se trouver notre animation à un moment donné pour simuler un effet particulier.
Regardez la figure suivante : en rouge, sans interpolation, la vitesse de votre animation reste identique pendant toute la durée de l'animation. En bleu, avec interpolation, votre animation démarrera très lentement et accélérera avec le temps. Heureusement, vous n'avez pas besoin d'être bons en maths pour utiliser les interpolateurs.
Vous pouvez rajouter un interpolateur à l'aide de l'attribut android:interpolator
, puis vous pouvez préciser quel type d'effet vous souhaitez obtenir à l'aide d'une des valeurs suivantes :
@android:anim/accelerate_decelerate_interpolator
: la vitesse est identique au début et à la fin de l'animation, mais accélère au milieu.@android:anim/accelerate_interpolator
: pour une animation lente au début et plus rapide par la suite.@android:anim/anticipate_interpolator
: pour que l'animation commence à l'envers, puis revienne dans le bon sens.@android:anim/anticipate_overshoot_interpolator
: pour que l'animation commence à l'envers, puis revienne dans le bon sens, dépasse la valeur finale puis fasse marche arrière pour l'atteindre.@android:anim/bounce_interpolator
: pour un effet de rebond très sympathique.@android:anim/decelerate_interpolator
: pour que l'animation démarre brutalement et se termine lentement.@android:anim/overshoot_interpolator
: pour une animation qui démarre normalement, dépasse la valeur finale, puis fasse marche arrière pour l'atteindre.
Enfin, si on place un interpolateur dans un <set>
, il est probable qu'on veuille le partager à tous les enfants de ce <set>
. Pour propager une interpolation à tous les enfants d'un ensemble, il faut utiliser l'attribut android:shareInterpolator="true"
.
En ce qui concerne les répétitions, il existe aussi un interpolateur, mais il y a plus pratique. Préférez plutôt la combinaison des attributs android:repeatCount
et android:repeatMode
. Le premier définit le nombre de répétitions de l'animation qu'on veut effectuer (-1 pour un nombre infini, 0 pour aucune répétition, et n'importe quel autre nombre entier positif pour fixer un nombre précis de répétitions), tandis que le second s'occupe de la façon dont les répétitions s'effectuent. On peut lui affecter la valeur restart
(répétition normale) ou alors reverse
(à la fin de l'animation, on effectue la même animation mais à l'envers).
L'évènementiel dans les animations
Il y a trois évènements qui peuvent être gérés dans le code : le lancement de l'animation, la fin de l'animation, et chaque début d'une répétition. C'est aussi simple que :
1 2 3 4 5 6 7 8 9 10 11 12 13 | animation.setAnimationListener(new AnimationListener() { public void onAnimationEnd(Animation _animation) { // Que faire quand l'animation se termine ? (n'est pas lancé à la fin d'une répétition) } public void onAnimationRepeat(Animation _animation) { // Que faire quand l'animation se répète ? } public void onAnimationStart(Animation _animation) { // Que faire au premier lancement de l'animation ? } }); |
- Chaque type de ressources aura comme racine un élement
resources
qui contiendra d'autres éléments hiérarchisant les ressources. Elles peuvent être accessibles soit par la partie JavaR.type_de_ressource.nom_de_la_ressource
soit par d'autres fichiers XML@type_de_ressource/nom_de_la_ressource
. - Les chaînes de caractères sont déclarées par des éléments
string
. - Android supporte 3 types d'images : PNG, JPEG et GIF, dans l'ordre du plus conseillé au moins conseillé.
- 9-Patch est une technologie permettant de rendre des images extensibles en gardant un rendu net.
- Les styles permettent de définir ou redéfinir des propriétés visuelles existantes pour les utiliser sur plusieurs vues différentes. Ils se déclarent par un élément
style
et contiennent une liste d'item
. - Les animations se définissent par un ensemble d'éléments :
<alpha>
pour la transparence d'une vue.<rotate>
pour la rotation d'une vue autour d'un axe.<scale>
pour la modification de l'échelle d'une vue.<translate>
pour le déplacement d'une vue.
- L'animation sur un layout se fait grâce à la déclaration d'un élément
LayoutAnimation
. - Une interpolation peut être appliquée à une animation pour modifier les variations de vitesse de l'animation.