Archives mensuelles: October 2015

Programmation Android

Module Android 2

Développement d’une application mobile

Ce module est destiné à tout étudiant souhaitant apprendre à développer et publier une application Android, de la conception à la diffusion.

Les prérequis sont :

  • Module Android 1
  • Niveau correct en développement dans au moins un des langages suivant : Java, java-script ou Php. Java sera utilisé, mais avec beaucoup d’aide et l’utilisation des outils intégrés à Android Studio pour limiter le code à écrire.
  • Si votre projet implique un groupe de plus de 3 étudiants, git sera utilisé (mais toute l’aide nécessaire vous sera apportée). Git est très bien intégré à Android Studio, la ligne de commande n’est pas indispensable.

Compétences visées

  • Capacité à suivre la plupart des tutoriels disponibles (pour la mise en oeuvre de diverses fonctionnalités Android)
  • Savoir réaliser une application complète (avec l’aide de l’enseignant). Cette application peut être un projet tutoré ou personnel, elle peut être décidée avant ou pendant le module. Il peut s’agir aussi bien d’un jeux que d’un utilitaire.
  • Toute compétence utile à votre projet (ex : boucle d’animation pour un jeu, téléchargement en tache de fond pour un utilitaire etc…), à la demande (n’hésitez pas à demander un cours sur un point dont vous avez besoin)
  • Diffusion de l’application (fichiers APK, mise en ligne sur un compte Google Play)
  • En fonction de l’avancement du projet, une partie sur la monétisation (comment gagner de l’argent avec une application) est envisageable.

Contenu

Vu l’objectif, le contenu est très fortement adaptable, et sera modifié pour coller aux projets des étudiants. Presque tout les sujets possibles sont envisageables. A titre indicatif :

  • Design avancé (gestion des listes et grilles, modification dynamique de l’interface)
  • Utilisation des outils de génération de code et refactoring intégrés à Android Studio.
  • Gerer la persistance des données (conserver les informations de l’application d’un lancement à l’autre).
  • Respect des consignes de développement de Google (ex : Material Design)
  • Gestion des actions asynchrones (comment gérer correctement les calculs longs, ou les téléchargements etc…)
  • Utilisations du GPS, de l’accéléromètre, de la boussole ou de l’appareil photo etc..
  • Base de la création d’un jeu simple (boucle d’animation) — (Attention, c’est difficile !)

TP

Android — Les listes (définies dans les ressources)
Android — Listes dynamiques
Android — Images dans les listes et grilles
TP Android : Téléchargement d’un fichier
TP Android : Utilisation de SQLite
TP Android : Les sons (bruitages)
TP Android : Les sons (musique)
TP Android : Les sons (musique en tache de fond)
Diffusion d’une application Android

Fiches de références

Les objets en Java (Bases)
Les objets en Java (Héritage)
Les objets en Java (Abstraction/Collections)
Android : gérer les tâches longues
Comment éviter de taper du code sous Android Studio ?
TP Android : partager un projet sur GitHub

Programmation Android

Android — Les listes (définies dans les ressources)

L’objectif de ce TP est d’apprendre à gérer les listes composées de texte avec un composant ListView. La première étape est la création d’une liste de textes dans un fichier xml, la suivante l’affichage de cette liste dans un composant ListView. On aborde ensuite la personnalisation des éléments de cette liste.

Création et utilisation d’un tableau de textes en xml.

Dans le fichier res/strings.xml, ajoutez une entrée de type string-array aux entrées déjà présentes :

<resources>
    <string name="app_name">Array</string>
     ...
    <string-array name="liste">
        <item>France</item>
        <item>Italie</item>
        <item>Belgique</item>
        <item>Espagne</item>
        <item>Suisse</item>
    </string-array>
</resources>

Ici, la liste ajoutée s’appelle « liste », et sera donc désignée par « @array/liste » en xml.

Dans le fichier de layout, ajoutez un ListView (vérifiez qu’il est assez grand et visible). Pour indiquer la liste à afficher, on utilise le champ « entry ». Ajoutez donc dans le ListView la ligne suivante (vous pouvez utiliser la complétion automatique) :

 android:entries="@array/liste"

Dans l’aperçu, on ne voit toujours pas le contenu de la liste s’afficher. C’est normal, tout ce qui concerne les listes est géré lors de l’exécution du code. Il faut donc lancer l’application pour voir le résultat.

Gestion du clic

Pour réagir à un clic sur une liste (par exemple, le choix d’un élément par l’utilisateur), il faut configurer le conteneur ListView pour qu’il déclenche un evènement, et gérer ensuite cet évènement. Cela nécessite quelques lignes de code :

Dans la méthode « onCreate », après le « setContentView() », on récupère l’objet correspondant au listView grace à son identifiant (par exemple R.id.listView), dans une variable listView :

ListView listView  = (ListView) findViewById(R.id.listView);

On configure ensuite l’activité (this : le fichier dans lequel on est) comme « écouteur » (listener en anglais) :

listView.setOnItemClickListener(this);

« this » est alors souligné en rouge, car actuellement notre activité ne gère pas les évènements de type clic sur un élément de liste. On y remédie avec alt-entrée, en choisissant « Make… implements … », ce qui conduit à l’ajout automatique d’une méthode onItemClic.

Dans cette méthode, on mettra le code à exécuter en cas de clic. On dispose dans le paramètre de type int du numéro de la ligne cliquée (int position).

Par exemple, on peut afficher dans un textView ce numéro en ajoutant le code :

  public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        TextView textView = (TextView) findViewById(R.id.textView);
        textView.setText("Clic sur ligne "+position);
    }

Style des éléments

Pour personnaliser le style des éléments de la liste, il faut rentrer un peu plus dans le fonctionnement d’un ListView. Le listView utilise un objet appelé « Adapter » pour gérer les composants afficher dans la liste. Cette gestion est complexe, mais réalisée automatiquement : les composants correspondant aux éléments sont remplis à partir des données (notre liste de textes), et réutilisés automatiquement quand on scrolle, pour éviter d’avoir à créer un objet par élément (pour des raisons de performance).
Heureusement, il suffit de configurer des « Adapter » déjà existants en leur fournissant notre feuille de style, et les données.

On commence par créer un nouveau layout pour les éléments à afficher dans la liste (par exemple, res/layout/element.xml) contenant un simple TextView comme élément de plus haut niveau (new -> Android resource File ->, et on choisit le nom du fichier, son type (layout), sa racine (TextView)). Pour la hauteur du composant, on choisit wrap_content (ou une hauteur fixe en dp).
On peut alors modifier dans le xml les attributs du texte (comme la couleur, les marges etc…). Ces modifications seront appliquées à tous les éléments de la liste.

Ensuite, dans le .java, il faut créer un nouvel adapter qui utilisera notre layout, et l’affecter au listView ( seules les trois dernières lignes sont à ajouter, le reste est normalement déjà présent:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView listView  = (ListView) findViewById(R.id.listView);
        listView.setOnItemClickListener(this);
 
        // Configuration de l'adapter :
        String[] list = getResources().getStringArray(R.array.liste);
        ArrayAdapter adapter = new ArrayAdapter(this,R.layout.element,list);
        listView.setAdapter(adapter);
    }

Dans ce code, la liste est d’abord récupérée dans la variable list. Ensuite, l’adapteur est créé en utilisant le layout element et la liste. Enfin, le listView est configuré pour utilisé l’adapeur.

Attention, il faut maintenant retirer la ligne « entry=… » du xml, puisqu’on la récupère directement en java avec l’adapteur.

Remarque : pour un layout d’éléments plus complexe qu’un simple TextView, on peut utiliser la même technique mais en fournissant en plus le R.id du textView à utiliser pour le texte.

Utilisation du contenu de la liste en java

Vu que l’on récupère la liste de texte dans un tableau, on peut maintenant afficher les éléments de la liste dans notre textView, et pas juste le numéro de ligne. Pour cela, il faut avoir accès à la variable list dans la méthode onItemClick. Or, pour l’instant, la variable list est déclarée dans onCreate, et donc visible uniquement de cette méthode. Il faut donc transformer cette variable en champ, qui sera utilisable partout dans notre activité. Cela se fait simplement sous android studio : on double-clic sur la variable, et ensuite on utilise le menu contextuel (refactor->extract->field) ou directement ctrl-alt-f, et on valide. La variable est maintenant déclarée dans la classe, et deviet visible dans toutes les méthodes. Dans le onItemClick, on remplace position par list[position].

Programmation Android

Android — Actions

L’objectif de ce TP est d’apprendre à configurer certains composants de manière plus complète qu’en xml, et associer des actions à différents évènements (comme l’utilisation d’un bouton). Pour cela, la première étape est d’apprendre à trouver les fichiers .java associés à chaque activité.

Fichier .java associé à une activité

Dans les TP précédents, vous avez appris à créer le design d’une activité en manipulant les fichiers .xml des répertoires. Ces fichiers sont utilisés par des fichiers .java, qui ont été crée automatiquement par l’assistant de création d’activité. Si les noms des fichiers n’ont pas été modifiés, il est facile de trouver le fichier java associé au fichier xml en regardant les noms (il est d’ailleurs recommandé de respecter les conventions de nommage utilisées par défaut dans Android Studio). Néanmoins, il est intéressant aussi de comprendre comment Android associe les fichiers java et la mise en page :

  • Le fichier manifest.xml recense les activités de l’application, à l’aide d’une balise activity. L’attribut name précise la classe associée à l’activité
  • En Java, chaque classe est décrite dans un fichier .java. Ces fichiers sont organisés en paquets, chaque paquet correspondant à un sous-répertoire du répertoire java du projet. Le répertoire racine est précisé dans le manifeste, dans l’attribut package de la balise de plus haut niveau (manifest)
  • Attention, il faut remplacer les . présents dans le nom du paquet par des / pour trouver le nom du répertoire.

Vérifiez que le fichier .java de votre activité se trouve bien à l’emplacement décrit dans votre manifeste.xml

Composition du fichier .java

Le fichier .java créé automatiquement contient le code permettant d’assembler l’interface conformément au contenu du fichier xml correspondant. Pour le détail de l’organisation des fichiers java, consultez le lien donné à la fin de ce TP.

Une fois le fichier ouvert sous Android Studio, on peut basculer du mode projet au mode structure (tout à gauche, en bord de fenêtre). On voit ainsi la liste des champs (il n’en a pas pour l’instant) et celle des méthodes. Cliquez sur la méthode onCreate(Bundle) pour naviguer directement dessus. Cette méthode, comme son nom l’indique, est appelée lors de la création de l’activité. C’est là que l’interface doit être assemblée. Le code est très simple :

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Ajoutez votre code à partir d'ici (si on le met avant l'appel à setContentView(),
        // les vues n'ont pas encore été crées.
        Button button = (Button) findViewById(R.id.button);
        // La ligne présente permet par exemple de récupérer un bouton dans la variable button.
        // On pourrait ensuite ajouter du code pour le configurer.
    }

La première ligne indique que l’on appelle la méthode onCreate de l’ancêtre de notre activité. C’est là que le code commun à la création de toutes les activités est exécuté.

La deuxième ligne lance la création proprement dite de l’interface. l’expression R.layout.activity_main est simplement la version java de l’identifiant xml @layout/activity_main, qui désigne donc le fichier res/layout/activity_main.xml .
R est une classe java créée automatiquement à partir des fichiers du répertoire des, pour faire le lien entre les ressources et le code java.
Attention :

  • Il ne faut jamais éditer ce fichier R.java
  • Quand il y a une erreur dans un des fichiers du répertoire res, le fichier R.java ne peut être créé correctement. Du coup, R est signalé comme une erreur dans le code java, alors que le problème est dans les ressources (le plus fréquent étant les noms d’images incorrects). Pensez-y si Android studio vous indique une erreur sur R dans un fichier .java

C’est dans la méthode onCreate, juste après l’appel à setContentView, que l’on peut récupérer et configurer les composants (View) directement en Java.

Récupérer un composant

La méthode setContentView utilise les informations du fichier .xml de mise en page pour créer et configurer les différents composants (View) affichés à l’écran. Ces composants représentent l’interface, donc toute modification de l’état d’un de ces objets se traduit potentiellement à l’écran. Pour modifier ce qui est affiché (par exemple le texte d’un bouton), il suffit de récupérer l’objet correspondant, et de lui donner l’ordre correspondant à la modification que l’on souhaite réaliser.

Pour obtenir l’objet associé à un composant, il faut déclarer une variable du même type, et placer l’objet correspondant à l’identifiant dans cette variable. Ces deux informations se trouvent dans le fichier xml de mise en page. Par exemple, pour récupérer un composant de type textView :

  1. Localisez le composant dans votre xml (le plus rapide est de cliquer dessus dans l’aperçu graphique, en étant en mode xml).
  2. Le texte de la balise est le nom de la classe à utiliser (ex : TextView)
  3. Le champ id contient votre identifiant (ex : android:id= »@+id/textView »)

La ligne à ajouter est de la forme suivante :

TextView textView = (TextView) findViewById(R.id.textView);

On remarque que le nom de la classe est utilisé deux fois (TextView), et que l’on peut utiliser comme nom de variable le nom de la classe, mais en commençant par une minuscule (textView). L’identifiant @+id/textView a été transformé (en un nombre entier constant et unique) en utilisant R : R.id.textView. On voit maintenant pourquoi il est important de choisir des noms explicites pour les identifiants : cela évite d’avoir à basculer entre le fichier java et fichier xml pour écrire le code, la complétion automatique permettant alors de s’y retrouver facilement.

Astuce : Sous android studio, il suffit de taper « TextView textview = fbc » puis la touche tab, valider (TextView) avec tab, choisir la référence R.id…. et la valider avec tab.

Si Android studio signale une erreur sur le type, il suffit de se placer sur la ligne concernée et un appui sur Alt-entrée corrigera automatiquement le problème en ajoutant une directive d’import en début de fichier (pour expliquer où est défini le type manquant).

Une fois la vue récupérée dans un objet, on peut configurer ses propriétés avec des setters (méthodes dont le nom commence par set, et qui servent à modifier un champ).
par exemple :

textView.setText("Nouveau texte");

Remarque : il faut mieux placer votre texte dans une ressource de type String (dans des/values/strings.xml), et appeler ensuite textView.setText(R.string.nouveau), afin de faciliter l’internationalisation.

Pour savoir quelles propriétés vous pouvez modifier, il suffit de consulter l’aide en ligne (recherchez Android et le nom de la classe, et ouvrez la première page sur le site d’android developer) ou d’utiliser la complétion automatique (ctrl – espace).

Changer la police de caractère

Il est possible d’utiliser un fichier fichier .ttf comme police de caractère pour n’importe quel composant. Pour cela, on charge le fichier dans un objet, puis on l’applique à chaque composant visé. Voici comment procéder pour un composant :

Mettre le fichier .ttf dans un répertoire nommé assets/, répertoire placé (ou à créer) au même niveau que res/ .
Ensuite, dans le onCreate et après l’appel à setContentView, mettre le code pour charger le .ttf et l’appliquer :

Typeface myTypeface = Typeface.createFromAsset(this.getAssets(), "exemple.ttf"); 
         // Charge la police dans myTypeface
 
TextView textView = (TextView) findViewById(R.id.textView);
           // Récupère le composant auquel appliquer la police
 
textView.setTypeface(myTypeface); // Change la police du composant

A noter qu’avec cette technique, il faut changer individuellement la police de chaque composant. On peut bien sur faire une fonction qui parcours toutes les vues pour appliquer automatiquement la nouvelle police, mais on sort alors du cadre de ce TP.

Associer une action à un bouton

Pour associer une action à un clic, il faut :

  • Créer une méthode contenant le code de l’action, dans la classe associée à votre mise en page.
  • Indiquer dans le champ onClick du composant souhaité le nom de la méthode à lancer

Configurer le champ onClick peut être fait soit dans le fichier layout (en xml, donc), soit dans le fichier de l’activité, après avoir récupérer l’objet button dans le onCreate() en appelant la méthode setOnClick(). Cette deuxième solution est un peu plus compliquée, modifiez plutôt le xml.

Ensuite, pour créer la méthode onClick (le nom de la méthode doit être celui donné dans le xml pour le champ onClick), insérez le code suivant (dans la classe Activity correspondant à votre activité, en dehors de toute méthode)

    public void onClick(View view){
        //Code de votre action
    }

A vous d’ajouter le code permettant de réaliser l’action souhaitée (comme changer le texte du bouton), par exemple en récupérant une vue et en la modifiant (comme on a fait dans le onCreate)

Remarque : le champ onClick est disponible sur tous les types de vue. On peut donc associer une action à un clic sur une image. Mais attention : l’utilisateur sait qu’il peut cliquer sur un bouton, il ne pensera pas nécessairement à essayer de cliquer ailleurs. De plus, un bouton réagit visuellement à un clic, ce n’est pas le cas de tous les composants.

Lancement d’activité

Une des actions que l’on peut placer dans un bouton consiste à démarrer une autre activité. Il peut s’agir d’une autre activité de la même application, ou quelque chose d’autre comme lancer un navigateur ou une autre application.

Le mécanisme utilise des objets particuliers, les Intent. Un intent peut représenter :

  • Une activité de l’application, indiquée par sa classe
  • Un type d’action que l’on souhaite réaliser, avec ses paramètres. Dans ce cas, le choix du programme à utiliser est laissé à l’utilisateur

Le code suivant permet de lancer une de vos activités (pensez à en créer une deuxième si nécessaire)

 Intent intent = new Intent(this, SecondActivity.class);
 startActivity(intent);

Pour lancer un navigateur sur google :

Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
startActivity(browserIntent);

Il existe beaucoup d’autres possibilités, comme appeler un numéro, consulter les information sur un contact etc :
Intent (javadoc)

Liens utiles

Le site android developer dispose d’un tutoriel correspondant à peu près à cette feuille, en expliquant comment lancer une activité avec un bouton, mais en un peu plus compliqué (du texte est envoyé d’une activité à l’autre et affiché)
Android developer : lancement d’une nouvelle activité

Aide-mémoire Java (fichier .java)
Aide-mémoire Android

Programmation Android

Android — images (utilisation avancée du xml)

Les ressources de type drawables, utilisables comme images de fond ou pour remplir un ImageView sont généralement des fichiers de type png ou jpg. Dans ce TP, nous allons voir comment utiliser des fichiers xml pour remplacer ou mieux utiliser des images.

La page de référence pour ce type de fichiers xml : drawable resources

Rectangles arrondis

Pour créer un fichier xml servant à dessiner un rectangle arrondi, on utilise le menu contextuel de res/ pour créer un nouveau fichier de ressource de type xml. Dans l’interface, on choisit un nom, le type de fichier (drawable) et l’élément de plus haut niveau (pour nous, shape). On obtient ainsi un nouveau fichier :


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFF00FF"/>
<corners android:radius="24dp"/>
</shape>

Pour préciser la couleur, on ajoute un élément « solid » avec un champ « color ». On définit le rayon des coins avec un élément corner et son champ radius ce qui donne par exemple :


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFF00FF"/>
<corners android:radius="24dp"/>
</shape>

il est possible d’ajouter en plus un bord avec la balise stroke et les champs width et color.

Pour voir à quoi ressemble votre fichier xml, il suffit de l’affecter comme background à un élément de votre mise en page (par exemple à un layout ou à un texte)

Dégradés

Une autre utilisation commune de shape est la création de dégradés. La technique est la même que ci-dessus, seuls les éléments à l’intérieur de shape changent. L’exemple donné par la documentation est le suivant :

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:startColor="#FFFF0000"
        android:endColor="#80FF00FF"
        android:angle="45"/>
    <padding android:left="7dp"
        android:top="7dp"
        android:right="7dp"
        android:bottom="7dp" />
    <corners android:radius="8dp" />
</shape>

(Les parties padding et corner ne sont pas indispensables, en particulier si on ne veut pas mettre le dégradé dans un rectangle arrondi)

Placement d’une image de fond

Le positionnement et le redimensionnement d’une image ne sont pas possibles directement quand on utilise celle-ci en image de fond. La solution consiste à passer par un fichier xml permettant d’associer à une image le comportement souhaité. La méthode est la même que précédemment, mais avec bitmap comme élément de plus haut niveau à la place de shape. L’image utilisée est précisé par un lien vers la ressource dans le champ src.

Répétition dun motif

La répétition permet d’utiliser une image comme texture, sans avoir à fournir une image de dimensions élevées. Il suffit de préciser dans le champ tileMode la valeur « repeat » (ou « mirror »)

Mise à l’échelle sans déformation

Par défaut, une image de fond est redimensionnée à la taille de la vue. Le champ gravity de l’objet bitmap permet de préciser comment déformer l’image.

  • top,bottom,left,right,center : positionne l’image sans redimensionnement.
  • fill_vertical, fill_horizontal : redimensionne l’image pour remplir la vue verticalement ou horizontalement.
  • clip_vertical, clip_horizontal : coupe l’image, en prenant en compte le positionnement
Programmation Android

Android — adaptation aux différents terminaux

Android fonctionne sur une grande variété de machines, du petit téléphone à la tablette 12″ (auxquels s’ajoutent maintenant des montres, télé et même voitures). Pour qu’une application soit agréable à utiliser sur des périphériques très différents, il est nécessaire d’adapter l’interface. Android utilise pour cela un mécanisme ingénieux de noms de répertoires, qui évite d’avoir recours à du code lors de la prise en compte de la taille de l’écran, sa densité, la langue de l’utilisateur etc…

Les qualificateurs

Comme on l’a vu lors du précédent TP, les fichiers de configuration se trouvent dans les sous-répertoire du répertoire /res. Pour chacun de ces sous-répertoires, il est possible de fournir plusieurs variantes en créant un nouveau répertoire avec un (ou plusieurs) suffixes séparés par un – . Quand un programme a besoin d’un fichier ou d’une ressource, le système recherche automatiquement le répertoire le plus adapté contenant une version du fichier ou de la ressource demandé, en utilisant en dernier recours le répertoire sans suffixe.

Afin de ne pas encombrer l’interface, Android studio affiche par défaut tous les fichiers présents dans au moins un des répertoires, en précisant le suffixe après le fichier (si il n’y en a qu’un), ou le nombre de variantes (avec possibilité de donner le détail). pour afficher les répertoire réel, il suffit de placer Android studio en mode projet (n’oubliez pas de revenir en mode Android après), comme on a pu le faire pour ajouter une image dans le TP 1.

Orientation

Dans l’éditeur graphique, on peut basculer l’aperçu de la mise en page entre les modes portraits et paysages avec le bouton comportant un téléphone et une petite flèche bleu (au dessus de l’aperçu). Par défaut, c’est simplement le même fichier de mise en page qui est utilisé sur une orientation différente. Par contre, si on créé une variante dans le répertoire layout-land, c’est la mise en page correspondante qui est affichée.

L’éditeur graphique d’Android Studio permet de créer simplement ce ficher de mise en page pour le mode paysage. Pour cela, ouvrez le menu accessible par l’icône avec la page et la tête de droid (en haut à gauche de l’éditeur), et sélectionnez « Create landscape variation ». Le répertoire layout-land a été créé, et le fichier de mise en page par défaut recopié dedans. A noter que l’on peut faire la même chose manuellement. Pour cela, utilisez le menu contextuel sur l’arborescence du projet, choisissez « new », puis « ressource directory ». Pour le champ « ressource type », choisir layout. Ajoutez ensuite le modificateur appelé orientation avec comme valeur landscape. Le répertoire layout-land est ainsi créé. En cliquant sur le fichier de mise en page original, choisir dans le menu contextuel refactor puis copie et en enfin le répertoire qui vient d’être créé comme destination.

Une fois que le fichier de mise en page alternatif pour le mode paysage existe, les deux fichiers sont complètement indépendants. Pour modifier l’un ou l’autre, il suffit dans l’éditeur de changer l’orientation de l’aperçu. A noter que si on ne créé pas de mise en page alternative, c’est le même fichier qui est utilisé (et donc modifié) dans les deux modes.

Dimensions de l’écran

En plus du qualificateur -land, il existe une grande variété de conditions (on peut en trouver un aperçu ici). Une des plus utiles pour la mise en page est la largeur de l’écran (en dp). Par exemple, les fichiers dans layout-w600dp ne seront utilisés que sur les écrans mesurant au moins 600dp de large. Le même menu de l’éditeur de mise en page qui vous a permis de créer la version paysage de votre application.

En fonction de l’application, il n’est pas toujours utile de réaliser une version paysage et une version pour écran large, le fait d’être en mode paysage pouvant parfois être un simple cas particulier d’écran large (mais évidemment pas très haut).

De même, il n’est pas toujours nécessaire de créer une nouvelle mise en page pour s’adapter à une taille en particulier, changer certaines dimensions est parfois suffisant. Dans ce cas, en utilisant des ressources de type dimension, et en fournissant une version spécifique de ces dimensions dans un répertoire comme values-w600dp, on évite la multiplication des mises en page et on facilite la maintenance de l’application.

Le répertoire values

Le répertoire des/values contient principalement des fichiers contenant les déclaration de valeurs référencées un peu partout dans les ressources (en utilisant le mécanisme d’identifiants présenté au TP précédent). Même si les noms des fichiers eux-même importent peu pour le compilateur, il est indispensable de respecter les conventions de nomades pour s’y retrouver. Les fichiers les plus courants sont :

  • string (pour les chaînes de caractère)
  • dimens (pour les dimensions)
  • style (pour regrouper les définitions d’attributs souvent utilisées)

Il est bien sur possible de rajouter vos propres fichiers, par exemple pour déclarer des couleurs et pouvoir les changer à un seul endroit.

Un bon usage de ces fichiers est indispensable au développement et à la maintenance de toute application destinée à être réellement diffusée (on peut s’en passer quand on cherche juste à tester comment faire ceci ou cela, par exemple). imaginons qu’une application gère 2 orientations, 3 tailles et 2 langues. Sans définition dans le répertoire values des dimensions et des textes pour chaque langue, il faudrait écrire 2x3x3 = 12 fichiers de mise en page par activité. Chaque modification de la mise en page imposerait donc de revoir ces 12 fichiers, avec les risques d’erreur et d’oubli. Si toutes les chaînes de caractères sont placées dans le fichier Strings.xml, on descend déjà à 6 fichiers. Si le mode horizontal et le mode écran large ne diffèrent que par les marges, on descend à 2 fichiers de mise en page, trois fichiers de dimensions, et deux fichiers de textes.

Les textes et dimensions utilisés directement (sans références à des ressources du répertoire values) génèrent un avertissement. En cliquant sur l’avertissement, on dispose d’un outil pour résoudre le problème. NB : attention au choix des noms des identifiants, qui doivent être des noms valides en Java.

Dans l’éditeur graphique, il est possible de choisir dans différents menus le type d’écran, la langue, la version d’android etc… afin de vérifier l’apparence qu’aura l’application dans diverses situations.

Bonnes pratiques

Dans le développement d’un projet sérieux sous Android, il est conseillé de respecter un certain nombre de pratiques et de conventions, pour faciliter le développement, la maintenance, et surtout pour éviter d’avoir à faire plusieurs fois le même travail. Lors du codage d’une interface, il est recommandé de procéder comme suit :

  • Créer une première version, en choisissant le cas le plus complet (par exemple tablette en mode horizontal)
  • « Nettoyer » les textes et dimensions, en les plaçant dans le répertoire values, créer des styles si nécessaires
  • Choisir les noms des identifiants des composants qui seront utilisés dans le code (ex : boutons), avec un format type ActiviteNomDescription
  • Créer et modifier les variantes de mise en page pour chaque cas

En procédant de la sorte, on évite d’avoir à refaire le même travail de nettoyage sur chaque version des fichiers de mise en page.