Cyril Mottier

“It’s the little details that are vital. Little things make big things happen.” – John Wooden

Créer Des Boutons Personnalisés

Note : Je tenais tout d'abord à m'excuser auprès des lecteurs de ce blog. En effet, voilà près de 3 mois que je n'ai rien posté concernant le développement sur Android. J'ai donc reçu quelques courriels me demandant la raison d'une telle “coupure” dans la rédaction de mes posts. La raison est assez simple : j'ai simplement été quelque peu débordé par les événements durant ces 3 derniers mois : finalisation de mes études, recherche d'un emploi, … vacances d'un mois et demi au pays des cow-boys :p et j'en passe. Je remercie sincèrement les lecteurs qui m'ont encouragé car il m'ont montré que le travail que j'entreprends sur ce blog n'est pas inutile et sert même à beaucoup. Pour les intéressés, j'ai trouvé un travail concordant avec mes préférences pour le monde “mobile” puisque je travaille sur les systèmes d'exploitation avancés tels qu'Android bien sûr mais aussi l'iPhone.

Pour ne pas brusquer mes petits neurones et les vôtres (mais également parce que je pense que parler de sujets extrêmement techniques sur ce blog implique que peu de lecteurs lisent et comprennent), je pense repartir sur des choses assez basiques. Ce post simple et facile d'accès traite de la création de boutons personnalisés.

Une interface graphique consiste à établir un lien entre le programme et l'utilisateur. La communication peut bien sûr s'effectuer à sens unique lorsque le programme affiche simplement des informations mais on se rend vite compte qu'une interface à “sens unique” n'a que peu d'intérêt. Imaginez notre bon vieux Android dépourvu de boutons … autant dire que l'utilisation devient rapidement déplorable et ennuyante :p. La plupart des interfaces graphiques contiennent donc des éléments de type “bouton”. Le look ‘n feel Android ne déroge pas à la règle et permet d'inclure des boutons dans les différents écrans de votre application.

Pour parfaire la “relation” entre l'interface et l'utilisateur, les boutons disposent en général de plusieurs états : normal, pressé, inactif, etc… L'utilisateur peut ainsi comprendre l'état d'un bouton suivant son image associée. Etudions, par exemple, le cas du bouton natif Android (dans sa version 1.6) : sa couleur change suivant son état courant :

  • Lorsqu'il est inactif (disabled), il est gris clair
  • Lorsqu'il est actif, il est gris légèrement foncé
  • Lorsqu'il a le focus, il est orange vif
  • Lorsqu'il est pressé, il est orange clair
  • etc.

Le développement d'un programme peut s'accompagner de la création d'un look ‘n feel propre à la marque/personne qui réalise l'application. L'objectif de cet article est donc d'étudier comment modifier l'apparence native des boutons Android et de mieux comprendre le principe de fonctionnement de ces derniers.

L'objet Button hérite de TextView héritant lui même de View. Il est donc possible d'accéder à l'attribut android:background de View et de le modifier afin de changer l'apparence native d'un bouton. Si vous effectuez cette opération (en modifiant simplement sa valeur à l'aide d'une image présente dans res/drawable, vous vous apercevrez que l'esthétique du bouton a bien changé mais ne se modifie pas en fonction des différents états de ce dernier. L'astuce réside en fait dans l'objet “foure-tout” (mais magnifiquement conçu) Drawable. Un Drawable est un objet pouvant “se dessiner”. Dans notre cas, il serait nécessaire d'avoir un Drawable qui change en fonction de l'état du bouton : un StateListDrawable!

StateListDrawable permet d'encapsuler plusieurs Drawables qui sont associés à un état (selected, focused, disabled, etc.). C'est grâce à ce type que nous allons pouvoir créer un bouton totalement personnalisé. Commençons tout d'abord par créer nos nouveaux boutons sous forme de 9-patchs (je ne pense pas avoir fait d'articles sur cette merveilleuse technique des 9-patchs - images extensibles - mais si certains lecteurs sont intéressés pour en savoir un peu plus, qu'ils n'hésitent pas à se manifester dans les commentaires) :

Il suffit maintenant de créer ce nouveau Drawable qui sera utilisé comme arrière plan de notre bouton. Comme d'accoutumé, deux possibilités s'offrent à nous : la méthode code, et la méthode XML. Assez partisan du “tout XML”, je vous conseille d'utiliser cette méthode car elle allège votre code et sépare bien la partie interface graphique de la partie métier. Le code d'exemple fourni plus bas montre une application utilisant les deux possibilités. EN XML, on utilise simplement la balise selector dans laquelle on ajoute tous nos Drawables sous la forme de balises item. Pour finir, on choisit les différentes valeurs des attributs android:state et android:drawable qui permettent tout simplement d'associer le Drawable à un état (fichier mybutton.xml mis dans res/drawable):

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/button1" android:state_enabled="true" android:state_window_focused="false"/>
    <item android:drawable="@drawable/button2" android:state_pressed="true"/>
    <item android:drawable="@drawable/button3" android:state_focused="true"/>
    <item android:drawable="@drawable/button1" android:state_enabled="true"/>

</selector>

Prenez garde à l'ordre des items dans la balise selector. En effet, lorsqu'on appui sur le bouton, le système lit les lignes dans l'ordre pour déterminer quel Drawable utiliser. Lorsqu'on appui sur un bouton, ce dernier est à la fois “pressed” et “enabled”. Si la ligne de l'état “enabled” avait été placée avant la ligne de l'état “pressed” dans l'exemple ci-dessus, le bouton n'aurait pas changé d'apparence car l'état “enabled” aurait été considéré comme viable par le système et donc utilisé en premier.

Cela peut sembler bizarre mais nous venons bien de créer un nouveau Drawable c'est à dire un objet “dessinable” à partir d'un fichier XML/texte. La dernière étape consiste donc à modifier la propriété android:background de notre Button pour que ce dernier change totalement d'apparence. Encore une fois, cette action s'effectue plus facilement via le XML :

1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/mybutton"
    android:text="New dummy content" />

Nous ne venons que d'effleurer les possibilités données par le package android.graphics.drawable. En effet des objets comme LevelListDrawable, NinePatchDrawable (mon préféré :p) ou AnimationDrawable facilite grandement l'utilisation des images sous Android. Pour bien montrer à quoi ressemble les boutons créés, j'ai développé une petite application d'exemple disponible ici: