1. Introduction

Lors d'un développement pour Android, j'ai eu besoin d'un objet graphique et les objets graphiques proposés par le SDK Android ne me convenaient pas.

J'avais besoin d'un indicateur de position afin d'aider l'utilisateur à se repérer lors de sa navigation dans les différents écrans et les seuls objets tout faits et disponibles les plus proches étaient la « scroll bar » ou la « progress bar ». Outre le fait que le graphisme ne me plaisait pas, ces objets ne répondaient pas à mon besoin qui était, comme sur une carte plane de la terre, lorsque l'on va continuellement vers la droite, on revient par la gauche, « MAX + 1 = MIN » et « MIN -1 = MAX », cet indicateur de position devait pouvoir « tourner ».

J'ai donc commencé à regarder comment créer de toutes pièces un tel objet et ce tutoriel est le résultat de cette recherche.

Cet article est organisé comme suit :

  • le paragraphe 2 spécifie mon besoin fonctionnel ;
  • le paragraphe 3 décrit l'implémentation de base ;
  • le paragraphe 4 décrit un projet de test qui utilise cet objet graphique ;
  • le paragraphe 5 laisse libre cours aux graphistes afin qu'ils expriment leur créativité ;
  • et enfin, le chapitre 6 se propose de conclure cet article.

2. Description du besoin fonctionnel

Dans le programme e-verbe pour Android, il y a un champ texte qui affiche le temps conjugué.

Lorsque l'utilisateur effectue un balayage horizontal sur ce champ texte, cela permet de changer le temps de la conjugaison (présent, imparfait, passé simple, futur simple…).

Lorsque l'utilisateur effectue un balayage vertical sur ce champ texte, cela permet de changer le mode de la conjugaison (indicatif, subjonctif, impératif, conditionnel…).

De plus, lorsque l'utilisateur est au dernier temps (ou mode) et qu'il continue son balayage vers la droite (ou vers le bas), il doit revenir au premier temps (ou mode).

De même, lorsque l'utilisateur est au premier temps (ou mode) et qu'il continue son balayage vers la gauche (ou vers le haut), il doit passer au dernier temps (ou mode).

Le besoin est donc de créer un indicateur de position qui permette à l'utilisateur de se repérer dans ses balayages.

Image non disponible

De plus, tous les modes de conjugaison n'ont pas le même nombre de temps (huit temps pour l'indicatif et deux temps pour l'impératif par exemple). Il faut donc un indicateur de position qui puisse se reconfigurer de manière dynamique.

Il y a bien les objets « scroll bar » ou « progress bar »qui existent dans le SDK Android mais ils ont plus une notion de « restant à parcourir » par rapport à « déjà parcouru » qu'une notion de « position courante » parmi un « ensemble de positions ».

Et en plus, ils répondaient difficilement à mon besoin de faire tourner ma position « MAX + 1 = MIN » et « MIN -1 = MAX ».

La copie d'écran ci-dessous montre le résultat obtenu :

Image non disponible

Il y a deux approches possibles de cette problématique :

  • l'indicateur de position est un objet actif sur lequel l'utilisateur peut agir. C'est donc l'indicateur de position qui est activé par l'utilisateur et c'est cet indicateur de position qui va demander à la vue de se rafraîchir en fonction de la position courante de l'indicateur de position ;
  • l'indicateur de position est un objet passif sur lequel l'utilisateur ne peut pas agir. C'est la vue qui est activée par l'utilisateur et qui demande à l'indicateur de position de refléter la position courante.

C'est cette deuxième approche que j'ai choisi d'utiliser.

3. L'implémentation de base

La classe de base de ce nouvel objet graphique est l'objet « GuiPositionIndicator » qui dérive de l'objet « View ».

Les fonctions et attributs implémentés par cette classe peuvent se classer en deux catégories (outre leur caractère privé, public ou protégé) :

  • ceux nécessaires aux fonctionnalités à implémenter. Les noms de ces fonctions sont préfixés par les caractères « Work » ;
  • ceux nécessaires et imposés par la classe « View ». Les noms de ces fonctions ne sont pas préfixés car leurs noms sont imposés par la classe « View » ;
  • les attributs (variables membres) sont en plus préfixés par les caractères « m_ ».

3.1. Les fonctions et attributs « Work »

Les fonctions et attributs « Work » à implémenter sont :

Nom Rôle
private void WorkInternalInit() Exécute l'initialisation des membres de la classe. Cette fonction est appelée par les constructeurs
public void WorkRolloverYes() Positionne le mode rollover (MAX + 1 = MIN et MIN - 1 = MAX)
public void WorkRolloverNo() Annule le mode rollover (MAX + 1 = MAX et MIN - 1 = MIN)
public final boolean WorkRollover() Indique si le mode rollover est positionné ou non
private boolean m_WorkRollover Variable mémorisant le statut du mode rollover
public void WorkSize(int Size) Fonction permettant d'indiquer le nombre de positions possibles
public final int WorkSize() Fonction retournant le nombre de positions possibles
private int m_WorkSize Variable mémorisant le nombre de positions possibles
public void WorkPos(int Pos) Fonction permettant d'indiquer la position courante
public final int WorkPos() Fonction permettant de récupérer la position courante
private int m_WorkPos Variable mémorisant la position courante
public void WorkPosNext() Fonction permettant d'avancer d'une position la position courante
public void WorkPosPrevious() Fonction permettant de reculer d'une position la position courante

3.2. Les fonctions et attributs « View »

Les fonctions et attributs « View » à implémenter sont :

Nom Rôle
public GuiPositionIndicator(Context context) Constructeur simple pour créer l'objet à partir du code
public GuiPositionIndicator(Context context, AttributeSet attrs) Constructeur utilisé pour créer l'objet à partir d'un fichier XML de ressources
public GuiPositionIndicator(Context context, AttributeSet attrs, int defStyle) Constructeur utilisé pour créer l'objet à partir d'un fichier XML de ressources tout en appliquant un style spécifique
protected void onDraw(Canvas canvas) Fonction appelée par Android pour redessiner l'objet graphique

3.3. Le code complet de la classe « GuiIndicatorPosition »

Comme on peut le voir l'interface de la classe est très simple, il y a quelques fonctions nécessaires à la classe View. Les autres fonctions sont spécifiques à la fonctionnalité à implémenter.

Pour l'instant, le code de la fonction onDraw(), qui est en charge d'afficher l'objet graphique, est minimal. Il se contente de dessiner sa surface en vert et d'afficher la position courante par rapport au nombre de positions possibles. C'est dans cette fonction que les graphistes pourront s'exprimer.

Vous remarquerez aussi que l'on ne redessine pas l'objet graphique dans les fonctions « public void WorkSize(int Size) » et « public void WorkPos(int Pos) ». La vue est simplement invalidée par un appel à la fonction « invalidate') ». C'est le framework qui se chargera d'appeler la fonction « protected void onDraw(Canvas canvas) » dès que possible.

Le code de la classe « GuiIndicatorPosition » est le suivant :

 
CacherSélectionnez

3.4. La création d'un objet « GuiPositionIndicator »

L'objet « GuiPositionIndicator » est créé directement à partir du fichier XML de ressources comme ceci :

 
CacherSélectionnez

C'est le nom de l'attribut « Class » qui fait le lien avec notre classe « GuiIndicatorPosition ».

3.5. Le code de l'activité

L'initialisation de la classe GuiPositionIndicator peut être faite dans le constructeur de l'activité :

 
CacherSélectionnez

Vous remarquerez que :

  • l'initialisation des valeurs du contrôle « GuiPositionIndicator » est faite de manière très simple dans le constructeur de l'activité ;
  • il y a un EventListener qui écoute les clics de l'utilisateur. À chaque clic sur le texte, la position courante est avancée.

4. Exemple d'un projet complet

Un projet complet utilisant l'objet graphique « GuiPositionIndicateur peut être téléchargé ici. Vous remarquerez qu'il ne contient aucune fioriture, c'est le projet le plus simple qui soit.

4.1. Fonctionnement de l'exemple

Le fonctionnement de l'exemple est assez simple.

Il y a deux objets graphiques :

  • une fenêtre de texte (un objet Android « textView ») en gris qui affiche la position courante ainsi que la taille de l'indicateur de position ;
  • l'indicateur de position (un objet « GuiPositionIndicator ») juste en dessous qui affiche sous forme graphique la position courante et la taille.
Image non disponible

4.2. L'objet texte

4.2.1. La déclaration

L'objet texte est déclaré directement dans les ressources du projet :

 
CacherSélectionnez

4.2.2. L'initialisation de l'objet texte

L'initialisation de l'objet texte dans la fonction onCreate() de l'activité est basique :

 
CacherSélectionnez

Une fonction dédiée, la fonction RefreshText(), permet d'afficher le texte de la fenêtre ainsi que sa position courante :

 
CacherSélectionnez

4.2.3. Le gestionnaire d'événements

La partie la plus intéressante de l'objet texte est probablement le gestionnaire d'événements qui permet la gestion du balayage :

 
CacherSélectionnez

4.3. L'objet « GuiPositionIndicator »

4.3.1. La déclaration

L'objet « GuiPositionIndicator est déclaré directement dans les ressources du projet :

 
CacherSélectionnez

Il n'y a rien de particulier à signaler dans cette déclaration mise à part la ligne « class= » qui fait le lien entre cet objet graphique et la classe « GuiPositionIndicator ».

4.3.2. La partie graphique

La partie « artistique » de l'objet GuiPositionIndicator, se trouve sans surprise dans la fonction « onDraw() » :

 
CacherSélectionnez

4.3.3. L'initialisation

L'initialisation de l'objet « GuiPositionIndicator » se fait dans la fonction onCreate() de l'activité :

 
CacherSélectionnez

4.3.4. La modification de la position

La modification de la position de l'objet « GuiPositionIndicator » se fait dans le gestionnaire d'événements de la fenêtre de texte :

 
CacherSélectionnez

5. La parole est maintenant aux graphistes

Voilà, la « tambouille » Android est maintenant terminée, c'est aux graphistes d'exprimer leur créativité en remplaçant le code de la fonction onDraw(), cette tâche est largement au-dessus de mes possibilités.

À titre d'exemple, voici quelques compteurs qui pourraient être dessinés :

Image non disponible Image non disponible
Image non disponible Image non disponible
Image non disponible Image non disponible

6. Conclusions

Cet article est maintenant terminé et j'espère qu'il vous a montré qu'il est très facile d'implémenter un nouveau type d'objet.

Je suis complètement débutant avec cet environnement de développement et j'avoue que j'ai été agréablement surpris des possibilités graphiques qui sont offertes et des extensions possibles et faciles sous Android malgré un aspect un peu « rustique » au premier abord.

Votre avis et vos suggestions sur ce tutoriel m'intéressent ! Alors après votre lecture, n'hésitez pas : Commentez

Je tiens à remercier ClaudeLELOUP pour ses conseils avisés lors de la relecture de ce tutoriel.