ALLER PLUS LOIN DANS LE DÉVELOPPEMENT ANDROID



Documents pareils
Créer des applications Android

TP2 : Client d une BDD SqlServer

TP SIN Programmation sur androïde Support : eclipse

Outils, langage et approche Android Une introduction. Nicolas Stouls lyon.fr

Programmation des applications mobiles avec Android. 1 Inspiré du cours de Olivier Le Goaer

Warren PAULUS. Android SDK et Android x86

SOMMAIRE

Premiers Pas en Programmation Objet : les Classes et les Objets

Les fondamentaux du développement d applications Java

Table des matières. Partie I Concepts de base Préface... VII

TP au menu «UI ANDROID»

Encore plus de widgets et de conteneurs

Quelques patterns pour la persistance des objets avec DAO DAO. Principe de base. Utilité des DTOs. Le modèle de conception DTO (Data Transfer Object)

Android Publish/Subscribe, GCM, Google Cloud Messaging : une introduction

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

Programmer en JAVA. par Tama

Encapsulation. L'encapsulation consiste à rendre les membres d'un objet plus ou moins visibles pour les autres objets.

Android 4 Les fondamentaux du développement d'applications Java

1.3 Gestion d'une application

1. Base de données SQLite

Education Delivery Intelligent Tool

Développement tablette Android. SophiaConf2011 Par Arnaud FARINE

Programmation Android L3 informatique

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Alfstore workflow framework Spécification technique

Projet Android (LI260) Cours 2

Gestion des différentes tailles d écran

Utilisation d objets : String et ArrayList

Tutorial pour une application simple

Tp 1 correction. Structures de données (IF2)

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

Langage et Concepts de ProgrammationOrientée-Objet 1 / 40

Langage et Concepts de Programmation Objet. 1 Attributs et Méthodes d instance ou de classe. Travaux Dirigés no2

as Architecture des Systèmes d Information

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Guide d utilisation. Version 1.1

Générer du code à partir d une description de haut niveau

Plateforme PAYZEN. Définition de Web-services

JADE : Java Agent DEvelopment framework. Laboratoire IBISC & Départ. GEII Université & IUT d Evry nadia.abchiche@ibisc.univ-evry.

Développement Android. J.-F. Couchot

Optimiser pour les appareils mobiles

Environnements de développement (intégrés)

Android et le Cloud Computing

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Développement sous Android

Auto-évaluation Programmation en Java

TP1 : Initiation à Java et Eclipse

Génie Logiciel avec Ada. 4 février 2013

Institut Supérieur de Gestion. Cours pour 3 ème LFIG. Java Enterprise Edition Introduction Bayoudhi Chaouki

La base de données XML exist. A. Belaïd

Création d un service web avec NetBeans 5.5 et SJAS 9

Eclipse atelier Java

De Java à Android version 0.1

Chapitre 2. Classes et objets

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

Java Licence Professionnelle Cours 7 : Classes et méthodes abstraites

Formation. Module WEB 4.1. Support de cours

Licence Bio Informatique Année Premiers pas. Exercice 1 Hello World parce qu il faut bien commencer par quelque chose...

GESTION DES MENUS. Un menu est un ensemble de liens permettant la navigation dans le site.

Gestion distribuée (par sockets) de banque en Java

Projet gestion d'objets dupliqués

Interfaces graphiques avec l API Swing

Module Criteo Tags et Flux pour Magento

Java Licence Professionnelle CISII,

TD/TP PAC - Programmation n 3

Cette application développée en C# va récupérer un certain nombre d informations en ligne fournies par la ville de Paris :

BONNE NOUVELLE, À PARTIR DE DEMAIN 15 AOÛT 2014, l inscription en ligne sera disponible à partir du site de l ARO.

Introduction à Eclipse

Tutoriel Android - TP de prise en main

SYNC FRAMEWORK AVEC SQLITE POUR APPLICATIONS WINDOWS STORE (WINRT) ET WINDOWS PHONE 8

Chapitre VI- La validation de la composition.

PHILA-Collector-USB-16Go Pour Windows & Android

Chapitre 10. Les interfaces Comparable et Comparator 1

LMI 2. Programmation Orientée Objet POO - Cours 9. Said Jabbour. jabbour@cril.univ-artois.fr

Programmation mobile avec Android

TD/TP PAC - Programmation n 3

Bases Java - Eclipse / Netbeans

Un ordonnanceur stupide

CREG : versailles.fr/spip.php?article803

SYSTÈMES D INFORMATIONS

Initiation à JAVA et à la programmation objet.

BIRT (Business Intelligence and Reporting Tools)

Lambda! Rémi Forax Univ Paris-Est Marne-la-Vallée

OpenPaaS Le réseau social d'entreprise

Programmation par les Objets en Java

Projet Active Object

Cours d initiation à la programmation en C++ Johann Cuenin

La persistance des données dans les applications : DAO, JPA, Hibernate... COMPIL 2010 francois.jannin@inp-toulouse.fr 1

Présentation du langage et premières fonctions

Développement mobile MIDP 2.0 Mobile 3D Graphics API (M3G) JSR 184. Frédéric BERTIN

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

Plan du cours. Historique du langage Nouveautés de Java 7

Remote Method Invocation (RMI)

Outil de démonstration : Application PassNFC

Soon_AdvancedCache. Module Magento SOON. Rédacteur. Relecture & validation technique. Historique des révisions

RAPPELS SUR LES METHODES HERITEES DE LA CLASSE RACINE Object ET LEUR SPECIALISATION (i.e. REDEFINITION)

Prise en main rapide

Rapport de Stage Christopher Chedeau 2 au 26 Juin 2009

Programmation en Java IUT GEII (MC-II1) 1

Serveur d'archivage 2007 Installation et utilisation de la BD exist

Transcription:

ALLER PLUS LOIN DANS LE DÉVELOPPEMENT ANDROID Andr0 29 octobre 2015

Table des matières 1 Introduction 5 2 Fragmenter vos projets 7 2.1 Fragment...................................... 7 2.1.1 Introduction aux fragments......................... 7 2.1.2 Utiliser des fragments fixes......................... 10 2.1.3 Utiliser des fragments dynamiques...................... 14 2.1.4 Attacher un bundle.............................. 18 2.1.5 En résumé.................................. 20 2.2 ListFragment.................................... 21 2.2.1 Utilisation simple des listes......................... 21 2.2.2 Intégrer une vue personnalisée........................ 23 2.2.3 Vers des listes dynamiques.......................... 27 2.2.4 En résumé.................................. 31 2.3 Interfaces dynamiques............................... 31 2.3.1 Concevoir une interface dynamique..................... 33 2.3.2 Initialiser l activité hôte........................... 33 2.3.3 Communication entre les fragments..................... 35 2.3.4 En résumé.................................. 37 2.4 PreferenceFragment................................ 38 2.4.1 Définir ses préférences............................ 38 2.4.2 Intégrer ses paramètres dans une activité.................. 40 2.4.3 Affiner ses paramètres avec les en-têtes................... 41 2.4.4 Lire les préférences............................. 48 2.4.5 En résumé.................................. 49 2.5 DialogFragment.................................. 49 2.5.1 Créer un DialogFragment.......................... 49 2.5.2 Créer un AlertDialog............................. 52 2.5.3 Afficher une boite de dialogue........................ 54 2.5.4 En résumé.................................. 56 3 Conclusion 59 3.1 Remerciements................................... 59 3

1 Introduction Le développement mobile est devenu incontournable pour les entreprises. Elles se doivent d offrir des solutions mobiles pour leurs clients ou une vitrine mobile pour elles-mêmes. Le développement Android est d autant plus important puisqu il occupe une majeure partie du marché. Ce tutoriel n abordera pas de notions complexes mais les bases sont des pré-requis. Celles-ci peuvent être acquises dans ce tutoriel Android. Ce dernier aborde l utilisation des composants basiques du développement, nécessaire pour commencer. Dans le tutoriel ci-présent, un point d honneur est placé sur des notions utilisées en entreprise et couvrant une majeure partie des versions d Android. En effet, au vue de la diversité des constructeurs et des terminaux qu ils confectionnent, Google a du mal à migrer tous les smartphones vers la dernière version du système. C est pourquoi, la diversité est importante et il a fallu que Google puisse offrir une solution aux développeurs pour pouvoir maintenir et développer efficacement sur Android. Figure 1.1 Diagramme de la répartition des versions daté du 3 Juin 2013 Il sera enseigné le développement pour les nouveaux systèmes tout en restant compatible le plus possible vers les anciens systèmes (jusqu à Froyo en général). Ces notions sont, pour certaines, difficiles à acquérir tant les ouvrages sont peu nombreux sur les nouvelles fonctionnalités intégrées au système. L objectif est d aborder des notions avancées mais intéressantes sur le développement Android en restant accessible aux débutants. Tout ce qui figurera sera consciencieusement expliqué afin de vous permettre d en comprendre les concepts et de pouvoir les mettre en pratique directement, à travers des travaux pratiques sérieux. 5

1 Introduction Pour parvenir à atteindre cet objectif, une série de choses sont abordées : L utilisation de fragments pour confectionner des interfaces souples et avancées. Les derniers composants ajoutés dans les dernières versions d Android. La mise en place d un serveur pour effectuer des requêtes HTTP tout en gardant à l esprit le cycle de vie de l application et la batterie de l utilisateur final. [[information]] Tous les codes sources de ce tutoriel sont disponibles sur ce projet GitHub afin que vous puissiez consulter des exemples fonctionnels directement exécutables sur un terminal ou un émulateur. 6

2 Fragmenter vos projets Depuis Android 3.x, les fragments est apparus dans le développement d applications. Ils sont maintenant utilisés pour le développement de toutes les applications (du moins sérieuses) sur le Google Play Store. Ils permettent d isoler des portions d interfaces qui sont gérées par des classes héritant de Fragment plutôt que de Activity. Les fragments ressemblent aux activités, que cela soit dans son cycle de vie que dans les différentes sous-classes qu il peuvent créer. Ils se composent du type de base, des listes, des boites de dialogue et des écrans conçus pour paramétrer son application. Leurs utilisations seront expliquées via des exemples simples et claies pour présenter leurs fonctionnements. 2.1 Fragment Tout comme les activités, il existe un fragment «générique». Il peut inclure des listes, des écrans de préférences et toutes les vues du framework Android pour constituer des portions d interfaces. Par la suite, elles pourront être réutilisées plusieurs fois dans les écrans de l application finale. Pour expliquer en profondeur tous ces concepts, une explication détaillée des fragments est donnée dans la suite de ce chapitre. 2.1.1 Introduction aux fragments 2.1.1.1 Qu est ce qu un fragment? Les fragments ne sont pas simples à comprendre. Cette notion est souvent confuse pour les débutants et pas toujours bien comprise par les développeurs expérimentés. En effet, les possibilités offertes sont nombreuses et intéressantes. Les fragments sont à mi-chemin entre les activités et les vues. Il ne s agit ni de l un, ni de l autre mais ils sont étroitement liés avec ces concepts. Les fragments permettent de définir des morceaux d interfaces, un ensemble de vues, qu il est possible de contrôler et de réutiliser sur plusieurs écrans. En temps normal, une application est destinée à être exécutée aussi bien sur les smartphones que sur les tablettes, et peu à peu sur les télévisions connectées. La taille des écrans devient de plus en plus grande. Il faut pouvoir exploiter l espace efficacement sur chacune de ces plates-formes et, si possible, à partir d un seul projet. Ce dernier point sera expliqué bien plus tard dans ce cours au vue de sa complexité. Par exemple, le propriétaire d un blog pourrait légitimement vouloir développer sa propre application pour offrir une alternative mobile à ses lecteurs. Dans un blog simpliste, il voudrait permettre une consultation de ses articles et des commentaires associés. Une version smartphone consisterait dans l affichage de trois écrans : une liste des articles du blog, l article courant que 7

2 Fragmenter vos projets le lecteur consulte et les commentaires associés. Sur une tablette en mode paysage, il est possible de restreindre les écrans à un seul en affichant la liste des articles à gauche et l article et ses commentaire à droite. Ce genre de chose est possible grâce aux fragments! 2.1.1.2 Le cycle de vie des fragments Les activités sont régulées par un cycle de vie. Les fragments possèdent des similitudes sur ce point avec les activités. Ils définissent une interface qu ils contrôlent mais ils ne sont pas associés à un écran. Ils ne font que s y attacher. C est la raison pour laquelle leurs cycles de vie sont semblables mais pas identiques. Ils possèdent les méthodes callback d une activité, à savoir oncreate, onstart, onresume, onpause, onstop et ondestroy. Ces méthodes ont le même objectif que dans une activité. Elles ne seront pas (ou peu) expliquées. La documentation donne des informations à ce sujet en cas d oubli. Plusieurs nouvelles méthodes ont été rajoutées à travers ce cycle de vie. Elles sont liées à l activité hôte en cours d exécution. Il ne faut pas perdre à l esprit qu un fragment n est qu attaché à une activité. Les méthodes supplémentaires sont liées à cette activité. La documentation met à disposition un schéma pour donner le cycle de vie. Les méthodes rajoutées sont onattach, oncreateview, onactivitycreated, ondestroy- View et ondetach. Les noms de ces méthodes sont assez explicites. Deux sont destinées à la liaison avec l activité hôte, deux autres à la création de la vue qui compose le fragment et la dernière après la création de l activité hôte. Elles seront expliquées plus en détail dans la suite de ce chapitre ainsi que dans les suivants de cette partie. 2.1.1.3 La bibliothèque de compatibilité Le fragment est une nouveauté depuis Android 3.x. A partir de cette version, il est possible de les placer librement aux endroits voulus pour rendre les applications plus souples et les architecturer convenablement. Cependant, la version 2.3 d Android est encore largement utilisée, surtout dans les smartphones d entrée de gamme mais ils ne peuvent pas utiliser les fragments. Pourquoi ne pas avoir intégré les fragments dès le début? Google n a pas pu voir assez loin sur le long terme. Au début, Android était dédié uniquement aux smartphones. Les écrans avaient des tailles différentes en fonction du constructeur, voire du modèle, mais le marché des tablettes était presque inexistant. Les tailles ne dépassaient pas le 4 pouces. Une fois que les tablettes ont commencées à être commercialisées en grande quantité, Google a été contraint d offrir une alternative pour ce type d appareil. La version 3.x d Android était destinée à résoudre le problème mais ce n est qu à partir de la version 4 qu un tournant a pu être noté. Le plus grand défaut de la troisième version du système était sa philosophie. Même s il était meilleur que les versions précédentes, il n était pas prévu pour les smartphones. [[information]] Aujourd hui, de plus en plus de télévisions connectées sur Android sont commercialisées. Il est tout à fait possible de développer pour ce genre d appareil mais les bonnes pratiques d ergonomie sont encore un peu vagues. C est pourquoi, aucun exemple concret ne sera montré mais les techniques apprises dans ce tutoriel le permettront. Dans le but de ne pas devoir créer un projet pour chaque version d Android, Google a développé une bibliothèque de compatibilité qu il est possible d utiliser dans n importe quel projet. Cette 8

2.1 Fragment 9

2 Fragmenter vos projets bibliothèque donne accès à presque toutes les nouvelles notions qu apporte la version 3.x mais aussi la 4.x qui apporte son lot de nouveautés (elles seront expliquées dans la seconde partie). Grâce à cette bibliothèque, les applications développées toucheront plus de 90% du marché des appareils. Raison pour laquelle toutes les notions apprises seront basées sur son utilisation dès que possible. Il est également conseillé de développer avec ce projet même si l application finale n est pas destinée à être compatible avec les anciennes versons. Personne ne sait de quoi est fait demain. 2.1.2 Utiliser des fragments fixes!(http ://www.youtube.com/watch?v=z_qkuwcses4) La théorie maintenant terminée, la pratique permet d en comprendre réellement le fonctionnement. Il existe deux façons d intégrer des fragments à une activité : de manière fixe en spécifiant les fragments dans le fichier XML d affichage de l écran voulu et dynamiquement avec l aide des outils mis à la disposition des développeurs dans le framework Android. 2.1.2.1 Création d un fragment La création d un fragment est similaire à la création d une activité. La portion d interface se déclare dans un fichier XML d affichage. Il est désérialisé dans une classe qui étend la classe Fragment et non plus Activity. Cependant, même si les fragments peuvent redéfinir la méthode public void oncreate (Bundle savedinstancestate), y appeler la méthode setcontent- View(int resource) ne fonctionnera pas pour la désérialisation. Il est possible de redéfinir la méthode suivante dans son cycle de vie, public View oncreate- View (LayoutInflater inflater, ViewGroup container, Bundle savedinstancestate). Elle donne accès en premier paramètre à un «inflater» qui permet la désérialisation du fichier XML d affichage. La bibliothèque de compatibilité a été présentée. Son utilisation sera constante dans les exemples illustrant le tutoriel. Il existe une chose importante à savoir sur son utilisation : l environnement de travail, peu importe lequel, proposera d importer deux paquetages pour avoir accès à Fragment et aux autres classes présentées dans ce tutoriel. Pour les fragments, il proposera android.app.fragment et android.support.v4.app.fragment. Toutes les classes figurant dans les paquetages android.support.v4 possèdent un équivalent limité à une certaine API (à partir de la version 3.x d Android jusqu aux versions récentes). Quant à la bibliothèque de compatibilité, elle apporte une compatibilité à partir de la version 2.x. L utilisation des classes de cette bibliothèque diffère peu de l originale mais il y a certaines subtilités à connaître. Le tutoriel enseignera son utilisation plutôt que les originaux pour deux raisons : Il est plus simple de passer de l utilisation de la librairie de compatibilité vers les originaux que l inverse ; Les originaux restreignent la portée de l application finale au minimum à la version 3.x d Android, voire plus comme les notifications avancées qui ne sont compatibles qu à partir de la version 4.1. [[attention]] Les raisons pour utiliser la bibliothèque de compatibilité sont intéressantes mais il y a une chose essentielle à savoir : il n est pas possible de mélanger les originaux avec les classes 10

2.1 Fragment du support. C est une erreur commune chez les développeurs. Google a tenté de rendre l utilisation de la bibliothèque la plus proche de son utilisation normale. Mise à part quelques méthodes et des noms de classes, l utilisation sera identique. Cela peut paraître pratique mais une erreur est vite arrivée. Un fragment simple serait d afficher simplement du texte. Le but de cet exemple n est pas de confectionner un fragment complexe (ce loisir sera donné plus tard). L idée est de placer un Text- View au centre de l écran via un fichier XML d affichage. Il sera désérialisé dans un fragment qui sera lui même contenu dans une activité. Voici le fichier XML d affichage fragment_fixe : <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerhorizontal="true" android:layout_centervertical="true" android:text="@string/title_fragment_fixe" /> </RelativeLayout> Pour ce premier exemple, le fragment associé est extrêmement simple. En temps normal, un fragment joue le contrôleur complet de la portion d interface qu il contient afin d alléger l activité hôte et d architecturer convenablement le projet. Ainsi, le fragment FixeFragment ressemble à ceci : package com.siteduzero.android.fragments.fixe; import android.os.bundle; import android.support.v4.app.fragment; import android.view.layoutinflater; import android.view.view; import android.view.viewgroup; import com.siteduzero.android.r; public class FixeFragment extends Fragment { @Override public View oncreateview(layoutinflater inflater, ViewGroup container, Bundle savedinstancestate) { return inflater.inflate(r.layout.fragment_fixe, container, false); [[information]] Remarquez que les importations sont délibérément affichées afin de montrer que la bibliothèque de compatibilité est bien utilisée à la place des originaux. Cela sera une habitude prise dans ce tutoriel pour que vous ne soyez jamais perdus. 11

2 Fragmenter vos projets La création et l utilisation d un fragment est aussi simple qu une activité. Il faut maintenant attacher ce fragment à une activité. Il n y a aucun changement de ce côté là puisqu un fragment peut être déclaré dans un fichier XML d affichage comme n importe quelle vue. Il sera chargé dans une activité à l exécution de l application et ne changera plus. Dans ce cas, il sera fixé à l activité hôte. Ses attributs sont les mêmes qu une vue normale mais, en plus, il faut rajouter le chemin d accès vers le fragment. Pour attacher notre fragment FixeFragment, il faut le déclarer ainsi : <?xml version="1.0" encoding="utf-8"?> <fragment xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_fixe" android:name="com.siteduzero.android.fragments.fixe.fixefragment" android:layout_width="match_parent" android:layout_height="match_parent" /> Du côté de l activité, il y a une petite chose à savoir. Il n est pas possible d étendre la classe Activity si la bibliothèque de compatibilité est utilisée. Une autre classe est présente dans le support, FragmentActivity. Cette classe est l équivalente à la classe originale, Activity. Mais elle ne doit pas être utilisée si les originaux sont utilisés. package com.siteduzero.android.fragments.fixe; import com.siteduzero.android.r; import android.os.bundle; import android.support.v4.app.fragmentactivity; public class FixeActivity extends FragmentActivity { @Override protected void oncreate(bundle arg0) { super.oncreate(arg0); setcontentview(r.layout.activity_fragment_fixe); Tout comme le fragment, l activité est vide puisque le fragment est fixe et que toute l interface y a été déportée. C est l une des forces de l utilisation des fragments. Habituellement, les activités jouent le rôle des contrôleurs dans une architecture MVC (patron architectural sur lequel Android se base dans le développement d applications) mais cette partie contrôleur a été allégée pour ne plus avoir des activités énormes et pour devenir les contrôleurs des fragments plutôt que directement des interfaces. Cela permet de maintenir plus aisément le code et de séparer les responsabilités des différentes classes. 2.1.2.2 Réarranger les fragments en paysage Attacher un fragment de manière fixe à une activité n empêche pas d en attacher plusieurs, qu ils soient identiques ou non. Il suffit de spécifier plusieurs fragments dans le fichier XML d affichage de l activité pour voir apparaître les fragments. Une possibilité pour l illustrer est le mode paysage. Une application n est pas toujours destinée à s afficher en portrait (sauf en cas de contre indication dans le fichier Manifest) ni même toujours sur un smartphone. C est pourquoi, en mode 12

2.1 Fragment 13

2 Fragmenter vos projets paysage, il faut repenser les interfaces pour garder une expérience utilisateur optimale. Dans un dossier res/layout-land, il faut créer un nouveau fichier XML d affichage du même nom que celui dans le dossier res/layout de l activité cible, FixeActivity dans l exemple ci-présent. Tout comme n importe quelle vue, les fragments peuvent être placés dans un conteneur comme le LinearLayout afin de donner un poids équitable entre les fragments. <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:baselinealigned="false" android:orientation="horizontal" > <fragment android:id="@+id/fragment1" android:name="com.siteduzero.android.fragments.fixe.fixefragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> <fragment android:id="@+id/fragment2" android:name="com.siteduzero.android.fragments.fixe.fixefragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout> 2.1.3 Utiliser des fragments dynamiques Les fragments fixes sont simples à implémenter. A partir du moment où le fragment est codé, il suffit de l indiquer dans des fichiers XML d affichage à désérialiser dans une activité sans rien indiquer en plus. Se limiter à ce type de fragment ne permettrait pas de satisfaire ses promesses de flexibilité et de maintenance. Dans cet ordre idée, le framework Android fournit une API pour gérer les fragments pendant l exécution d une application. Ainsi, il est possible de remplacer un fragment par un autre aisément et, par la même occasion, afficher une nouvelle portion d interface. 2.1.3.1 Gérer ses fragments Le framework Android met à disposition des développeurs une API indispensable pour gérer les fragments, FragmentManager. Cette API offre plusieurs services. La documentation donne toutes les informations à ce sujet. Dans l immédiat, le plus intéressant est le service qui permet de gérer des transactions via une autre API, FragmentTransaction. Les transactions permettent d opérer sur les fragments de manière groupée. Les opérations sont classiques. Il 14

2.1 Fragment Figure 2.3 Résultat de l exécution de l activité FixeActivity en paysage est possible d ajouter, remplacer, supprimer, etc. des fragments. Elles ne seront pas toutes expliquées dans ce tutoriel. L utilisation de ces APIs est assez simple mais il faut garder à l esprit que la bibliothèque de compatibilité est utilisée dans les exemples. La documentation donnée renseigne les méthodes des classes originales du framework. Même si les signatures des méthodes sont globalement les mêmes pour chacune d elles, il arrive que quelques unes changent. Notamment avec l ajout du mot clé «Support». Par exemple, pour récupérer un FragmentManager, la méthode utilisée sera public FragmentManager getsupportfragmentmanager() plutôt que public FragmentManager getfragmentmanager(). [[attention]] Il faut rappeler que les fragments qui viennent du paquetage android.app.fragment ne peuvent pas être utilisés avec les classes de la bibliothèque de compatibilité (et inversement). Dans les exemples de ce tutoriel, Fragment et FragmentManager viennent tous les deux du projet de compatibilité. Dans le cas contraire, l application provoquera instantanément une erreur forcée. 2.1.3.2 Le contrôleur des fragments Jusqu à présent, le contrôleur des interfaces était les activités. Elles se chargeaient de désérialiser les fichiers XML et de récupérer les composants graphiques pour y ajouter un comportement et des évènements. Dorénavant, les fragments jouent ce rôle et les activités deviennent les contrôleurs des fragments. A savoir, les contrôleurs des contrôleurs. Il est essentiel de comprendre que les fragments ne sont pas vraiment des nouveautés dans leur rôle. Il y a qu une déportation du code d un concept à un autre. Le réel changement se situe dans les activités puisqu ils doivent gérer les fragments. Son changement de rôle est la réelle nouveauté. 15

2 Fragmenter vos projets Les fragments fixes n illustrent pas clairement ce principe. Même si le framework se charge d utiliser l API de gestion des fragments, il n est pas visuel pour le développeur. Pour l illustrer, deux fragments simples ont été confectionnés. Ils contiennent un TextView pour afficher le nom du fragment courant et un Button pour remplacer le fragment courant par le suivant. Ils ne sont pas compliqués à développer. Leurs réalisations sont disponibles sur le projet GitHub de ce tutoriel. Ils sont nommés Dynamic1Fragment et Dynamic2Fragment. Quant à l activité, elle a été nommée DynamicActivity. Plusieurs choses sont à savoir sur sa réalisation. Première chose, son fichier XML d affichage ne comportera aucun fragment mais un Frame- Layout avec un identifiant pour pouvoir le récupérer dans l activité et remplacer son contenu par celui d un fragment. Pour rappel, ce conteneur permet de superposer des vues à un même endroit sur l écran. Son utilisation sera plus claire par la suite. Seconde chose, pour des soucis de structuration et d apprentissage, une certaine architecture simpliste sera mise en place. Dans la méthode public void oncreate(bundle savedinstancestate), une méthode sera appelée : private void showfragment(final Fragment fragment). Elle affiche le fragment donné en paramètre. Elle sera appelée dans la méthode on- Create(...) et lorsque l utilisateur cliquera sur le bouton du fragment. 2.1.3.3 Initialisation des fragments L initialisation des fragments se fait par simple instanciation d un objet d un fragment confectionné précédemment. Par exemple, pour le premier fragment dynamique, il faudra procéder de la manière suivante : Dynamic1Fragment dynamic1fragment = new Dynamic1Fragment();. Cependant, comme il n existe pas de petites économies, une optimisation possible serait d instancier les deux fragments comme attribut de l activité. // We instantiate just one time fragments during the life of the activity. private final Dynamic1Fragment mdynamic1fragment = new Dynamic1Fragment(); private final Dynamic2Fragment mdynamic2fragment = new Dynamic2Fragment(); [[information]] Cette économie convient pour notre exemple mais nous verrons que cela changera bien vite lorsque l application deviendra plus complexe. 2.1.3.4 Remplacer les fragments Afficher le fragment à l écran est la réelle nouveauté dans le développement de fragments dynamiques. L idée est de remplacer le contenu du conteneur, FrameLayout, par un fragment donné. Pour ce faire, il est nécessaire d utiliser l API des transactions des fragments, FragmentTransaction. Sa documentation indique toutes méthodes utiles. Plusieurs sont utilisées dans showfragment(final Fragment fragment) : public abstract FragmentTransaction setcustomanimations (int enter, int exit) : Anime la transition d un fragment à un autre en donnant l animation d entrée pour le nouveau fragment et l animation de sortie pour l ancien ; public abstract FragmentTransaction replace (int containerviewid, Fragment fragment) : Remplace le contenu d un conteneur, donné en premier paramètre, par un nouveau fragment ; 16

2.1 Fragment public abstract FragmentTransaction addtobackstack (String name) : Indique une valeur null pour retourner au précédent fragment lorsque l utilisateur cliquera sur le bouton «Back». Au final, la méthode s implémentera de la façon suivante : private void showfragment(final Fragment fragment) { if (fragment == null) { return ; // Begin a fragment transaction. final FragmentManager fm = getsupportfragmentmanager(); final FragmentTransaction ft = fm.begintransaction(); // We can also animate the changing of fragment. ft.setcustomanimations(android.r.anim.slide_in_left, android.r.anim.slide_out_right // Replace current fragment by the new one. ft.replace(r.id.framelayoutlistview, fragment); // Null on the back stack to return on the previous fragment when user // press on back button. ft.addtobackstack(null); // Commit changes. ft.commit(); [[attention]] Chaque transaction doit appeler la méthode commit() pour voir ses opérations s effectuer. En cas contraire, aucune erreur ne sera lancée mais rien ne se passera. 2.1.3.5 Retenir sa position dans les fragments Une astuce intéressante est de garder en mémoire le fragment affiché à l écran après une reconstruction de l activité. Il faut toujours privilégier l expérience utilisateur. Se souvenir de lui et de ses manipulations est un bon début dans cette idée. C est pourquoi, un nouvel attribut va figurer dans la classe pour retenir le fragment courant. Il suffira alors de le sauvegarder via la méthode public void onsaveinstancestate(bundle outstate). Le changement se fera dans la méthode oncreate(...) de l activité puisqu il faut afficher le fragment courant s il existe en mémoire. La méthode sera complétée de la façon suivante : if (savedinstancestate!= null) { mfragment = savedinstancestate.getstring(key_fragment); else { mfragment = getintent().getstringextra(key_fragment); if (mfragment!= null) { if (mfragment.equals(mdynamic1fragment.getclass().getsimplename())) { showfragment(this.mdynamic1fragment); else if (mfragment.equals(mdynamic2fragment.getclass().getsimplename())) { 17

2 Fragmenter vos projets showfragment(this.mdynamic2fragment); else { showfragment(this.mdynamic1fragment); [[attention]] Il faut remarquer qu une touche de réfléxivité est utilisée dans l exemple ci-dessus. mdynamic1fragment.getclass().getsimplename() renvoie le nom de la classe, à savoir Dynamic1Fragment. Il faut donc sauvegarder dans mfragment une valeur similaire qui se fera dans la méthode private void showfragment(final Fragment fragment) de la même manière avec la variable fragment. Ainsi, le fragment courant est sauvegardé. 2.1.3.6 Résultat final Avant de montrer le résultat final, il reste une problématique a résoudre : comment capturer l évènement des boutons des fragments dans l activité hôte? En effet, les fragments n ont pas accès à FragmentManager, ou plutôt, ce n est pas leur rôle de contrôler les autres fragments. En tant normal, il faut utiliser les listeners mais cette pratique sera expliquée plus tard. La technique utilisée est plus simple pour un premier aperçu des fragments dynamiques. Il faut utiliser un nouveau attribut dans les fichiers XML d affichage des fragments sur les éléments Button : android:onclick. Cet attribut permet de définir une méthode Java qui sera appelée automatiquement lorsque l utilisateur cliquera dessus. Il n y a que deux restrictions : La signature de la méthode doit être public, renvoyer void et avoir un seul paramètre du type View ; Elle doit être déclarée dans une activité. Les méthodes ressembleront à ceci pour des attributs avec les valeurs gotofragment2 et goto- Fragment1 : public void gotofragment1(view v) { showfragment(this.mdynamic1fragment); public void gotofragment2(view v) { showfragment(this.mdynamic2fragment); L exécution de l application permet d afficher un premier fragment avec un TextView qui ne change pas et un bouton qui propose à l utilisateur d afficher le second écran. Lorsqu il cliquera dessus, une animation sera exécutée vers le nouveau fragment. Lorsqu il cliquera sur le bouton «Back», il reviendra au précédent fragment. Le résultat est le suivant : 2.1.4 Attacher un bundle Les fragments deviennent les contrôleurs des interfaces qu ils désérialisent et ils sont indépendants les uns des autres. C est la force de ce nouveau concept mais il peut arriver, suivant les situations, qu à l initialisation d un fragment, des données soient nécessaires. Un exemple simple 18

2.1 Fragment 19

2 Fragmenter vos projets serait de donner l identifiant d un article. Sur base de cette donnée, le fragment peut récupérer toutes les informations de l article en question soit par un service web ou dans la base de données interne de l application. Les bundles ne sont pas utilisés qu avec les activités. Les fragments aussi peuvent les utiliser. Seulement, il n est pas question d Intent avec les fragments puisqu ils sont gérés par une autre API. La méthode avec les fragments est légèrement moins bien pensée que celle avec les activités. Il faut instancier un fragment, un bundle en plaçant les informations dedans et l attacher au fragment avec la méthode public void setarguments (Bundle args). MyFragment fragment = new MyFragment(); Bundle args = new Bundle(); args.putint(key_id, id); fragment.setarguments(args); Cette simple solution suffirait mais elle rencontre un problème : si l instanciation d un même fragment avec un bundle se fait plusieurs fois dans l application, il faut faire une répétition du code assez conséquente et la maintenir en cas de modification. Pour palier à cette répétition qui alourdie considérablement le code, une bonne pratique est de créer une méthode statique dans le fragment en question. Cela permet d encapsuler toutes les informations dans le fragment et de ne pas tout éparpiller dans le code. Cette méthode ressemblera à : public static MyFragment newinstance( /* informations que je veux donner à mon fragment */) { // renvoie une instance de mon fragment [[information]] Pour rappel, static signifie que la méthode n est pas directement attachée aux instances créé de la classe hôte. Par exemple, il est possible de créer des instances de la classe hôte dans cette méthode. En reprenant l exemple de l identifiant à passer au fragment pour afficher le contenu de l article sélectionné, il suffit de passer cet entier en paramètre, de reprendre le code précédemment donné et de renvoyer le fragment. Ainsi, dans le code de l application, il suffira d appeler la méthode MyFragment.newInstance(idArticle); pour automatiquement créer un fragment avec le bundle attaché et de modifier le code à un seul endroit en cas de changements. Pour récupérer les informations contenues dans le bundle du fragment, rien de plus simple. Les arguments sont accessibles par sa méthode d accès public final Bundle getarguments () qui renvoie le bundle précédemment attaché au fragment et d en récupérer les données grâce aux identifiants donnés à chacune. 2.1.5 En résumé Un fragment est une portion d interface qui peut être attaché à plusieurs activités différentes. Il possède son propre cycle de vie mais il est étroitement lié à son activité hôte. La bibliothèque de compatibilité Google permet de rendre les applications compatibles à partir des terminaux sur Android 2.1 et supérieur. 20

2.2 ListFragment Les fragments fixes sont attachés directement dans le fichier XML d affichage de l activité. Les fragments dynamiques sont attachés pendant l exécution de l application via une API, FragmentManager. 2.2 ListFragment Les listes sont, sans aucun doute, les composants graphiques les plus utilisés dans les applications mobiles, qu elles soient sur Android, ios ou autres. Elles permettent d afficher facilement des informations les unes à la suite des autres verticalement avec des vues personnalisées ou non pour chaque ligne. Plusieurs choses seront abordées dans ce chapitre : comment intégrer une liste mêlée à la puissance des fragments, personnaliser ses vues et la rendre dynamique en indiquant des vues spécifiques pour chaque ligne qui compose une liste. 2.2.1 Utilisation simple des listes Il existes deux possibilités pour intégrer une liste dans une application : la renseigner dans un fichier XML d affichage ou étendre la classe ListActivity. L équivalent avec les fragments est similaire à celle des activités à l exception près qu il faut tenir compte qu une liste ne peut pas être initialisée sans un contexte et qu elle n est créée qu une fois l activité hôte du fragment créée. 2.2.1.1 Déclarer sa liste dans des fichiers XML Une petite astuce méconnue consiste à coupler un fichier XML d affichage avec une classe qui étend ListFragment pour indiquer une vue à afficher si aucune ligne n est contenue dans la liste. Cet exemple illustrera les deux possibilités décrites précédemment. Sa mise en place est assez simple. Elle nécessite simplement l utilisation d identifiants déclarés dans le framework Android. Parmi tous les identifiants disponibles dans @android:id/, seulement list et empty sont nécessaires pour les listes. Dans le fichier XML d affichage destiné au ListFragment, il va falloir déclarer une ListView avec l identifiant @android:id/list et, dans le même fichier XML, au même niveau que la ListView, une autre vue dont l élément racine possèdera un identifiant @android:id/empty. Ainsi, lors de la désérialisation, le framework Android saura ce qu il devra charger lorsqu il y a des éléments dans la liste ou non. Dans un exemple où un simple texte est affiché au centre de l écran s il n y a aucun élément dans la liste, le fichier XML ressemblerait à : <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="wrap_content" 21

2 Fragmenter vos projets android:layout_alignparentleft="true" android:layout_alignparenttop="true" /> <TextView android:id="@android:id/empty" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerhorizontal="true" android:layout_centervertical="true" android:text="@string/text_empty" /> </RelativeLayout> 2.2.1.2 Création du ListFragment Le fragment ne sera plus aussi générique que celui du chapitre précédent. Afin de profiter de la création automatique d une ListView pour le fragment, la classe étendra ListFragment, parfait équivalent de la classe ListActivity. De la même manière que les fragments basiques, un ficher XML d affichage sera désérialisé dans sa méthode public View oncreate- View(LayoutInflater inflater, ViewGroup container, Bundle savedinstancestate) (chose qui n est pas obligatoire si aucune vue ne doit être affichée s il n y a aucun élément dans la liste). Comme avec une ListActivity, un adaptateur doit être attaché à la liste (adaptateur qui ne sera pas personnalisé pour le moment). L unique subtilité dans ce cas présent est la méthode à redéfinir. En effet, comme il faut un contexte pour initialiser un adaptateur, il faudra le créer, l initialiser et l attacher uniquement lorsque l activité hôte sera créée. Cela se fera dans la méthode public void onactivitycreated(bundle savedinstancestate). Ceci donne le code et le résultat suivant : package com.siteduzero.android.lists.simple; import com.siteduzero.android.r; import android.os.bundle; import android.support.v4.app.listfragment; import android.view.layoutinflater; import android.view.view; import android.view.viewgroup; import android.widget.arrayadapter; public class SimpleListViewFragment extends ListFragment { @Override public View oncreateview(layoutinflater inflater, ViewGroup container, Bundle savedinstancestate) { return inflater.inflate(r.layout.fragment_listview, container, false); 22

2.2 ListFragment @Override public void onactivitycreated(bundle savedinstancestate) { super.onactivitycreated(savedinstancestate); final String[] items = getresources().getstringarray(r.array.list_examples); final ArrayAdapter<String> aa = new ArrayAdapter<String>(getActivity(), android.r.layout.simple_list_item_1, items); setlistadapter(aa); 2.2.2 Intégrer une vue personnalisée La confection de vues personnalisées dans un ListFragment ne diffère pas de son équivalent avec une ListActivity. Cette personnalisation est complètement indépendante de son hôte. Par conséquent, certains aspects seront moins expliqués que d autres mais une piqûre de rappelle sera donnée, notamment sur l architecture à adoptée. 2.2.2.1 Créer une vue personnalisée Il faut créer plusieurs fichiers pour confectionner sa vue : son fichier XML d affichage et la classe qui le désérialise. Dans cet exemple, chaque ligne de la liste affichera un texte contenu dans un bloc avec un ombrage. Normalement, les ombrages dans le développement Android sont possibles uniquement grâce à la technologie 9-patch. Elle permet d étendre horizontalement ou verticalement certaines images sans les pixeliser. Cependant, le framework Android met à disposition des développeurs une série de ressources dont des ombrages. Le fichier XML d affichage pourra utiliser ces ressources pour afficher l ombrage et ressemblera alors à : <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:drawable/dialog_holo_light_frame" android:orientation="vertical" > <TextView android:id="@+id/textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="15dp" android:text="@string/default_lorem" /> </LinearLayout> Quant à la classe qui désérialise ce fichier XML, il doit étendre un conteneur, LinearLayout, redéfinir ses constructeurs et initialiser le texte avec la valeur souhaitée. Ce dernier point est possible 23

2 Fragmenter vos projets 24

2.2 ListFragment grâce à une méthode publique qui prend en paramètre l identifiant d une chaîne de caractères présente dans les ressources du projet. package com.siteduzero.android.lists.custom; import com.siteduzero.android.r; import android.content.context; import android.util.attributeset; import android.widget.linearlayout; import android.widget.textview; public class CustomListViewView extends LinearLayout { private TextView mtextview; public CustomListViewView(Context context, AttributeSet attrs, int defstyle) { super(context, attrs, defstyle); init(); public CustomListViewView(Context context, AttributeSet attrs) { super(context, attrs); init(); public CustomListViewView(Context context) { super(context); init(); private void init() { inflate(getcontext(), R.layout.view_custom_listview, this); mtextview = (TextView) findviewbyid(r.id.textview); public void bind(int text) { mtextview.settext(getresources().getstring(text)); 2.2.2.2 Créer son adaptateur La création d un adaptateur prend tout son sens à partir du moment où une ListView est constituée de vues personnalisées. Un adaptateur doit étendre la classe BaseAdapter, redéfinir les méthodes obligatoires (il existe des méthodes facultatives pour des listes dynamiques, cela fera l objet du prochain point de ce chapitre) et permettre de rajouter les données à injecter dans la liste. Ces données peuvent être aussi simples que complexes. Il en revient au développeur d injecter l «intelligence» nécessaire dans son adaptateur. 25

2 Fragmenter vos projets La chose à savoir dans la création d un adaptateur est la façon d implémenter la méthode public View getview(int position, View convertview, ViewGroup parent). Dans les applications mobiles, il est nécessaire d économiser la moindre zone mémoire possible. Ainsi, lorsque l utilisateur parcourt une liste, si la vue d une ligne est encore en zone mémoire, il est préférable de la réutiliser plutôt que d en créer une nouvelle. Raison pour laquelle cette méthode renvoie une vue en second paramètre. L adaptateur s implémente donc de la manière suivante : package com.siteduzero.android.lists.custom; import java.util.arraylist; import java.util.list; import android.content.context; import android.view.view; import android.view.viewgroup; import android.widget.baseadapter; public class CustomListViewAdapter extends BaseAdapter { private List<Integer> mmodel = new ArrayList<Integer>(); private Context mcontext; public CustomListViewAdapter(Context context) { mcontext = context; @Override public int getcount() { return mmodel.size(); @Override public Integer getitem(int position) { return mmodel.get(position); @Override public long getitemid(int position) { return position; @Override public View getview(int position, View convertview, ViewGroup parent) { CustomListViewView v = null ; // Notre vue n'a pas encore été construite, nous le faisons if (convertview == null) { v = new CustomListViewView(mContext); // Notre vue peut être récupérée, nous le faisons 26

2.2 ListFragment else { v = (CustomListViewView) convertview; v.bind(getitem(position)); return v; public void bind(list<integer> model) { mmodel = model; Puisque l objectif est d utiliser les fragments, le fragment hôte s occupera d envoyer les données via la méthode public void bind(list<integer> model) de l adaptateur après son initialisation. L utilisation d un adaptateur personnalisé est toute aussi simple qu un des adaptateurs donnés à la disposition des développeurs par défaut dans le framework. Le résultat correspond à la capture suivante : 2.2.3 Vers des listes dynamiques Une liste dynamique réside dans les différentes vues possibles à appliquer pour ses lignes. A la place de s arranger avec une ScrollView et d ajouter des vues dynamiquement à ce conteneur grâce à d autres conteneurs, le framework Android fournit une solution élégante juste en redéfinissant deux autres méthodes dans un adaptateur personnalisé. 2.2.3.1 Nouvelles méthodes de l adaptateur L exemple qui illustrera cette liste dynamique consistera à afficher un «header» avec une image à gauche et du texte à droite. Une seconde vue sera un «body» avec simplement du texte (comme la vue du point précédent de ce chapitre). La création de ces vues ne sera pas abordée dans la suite de ce chapitre vu sa simplicité. Concernant l adaptateur, pour indiquer qu il va devoir gérer plusieurs vues différentes dans sa liste, deux méthodes, liées au type de la vue courante à instancier, doivent être redéfinies : public int getviewtypecount() : Indique combien de vues différentes comportent la liste ; public int getitemviewtype(int position) : Indique le type de la vue à instancier pour la ligne courante. Pour implémenter ces méthodes, il faudra plusieurs constantes et une liste représentant les types. Cette manière de faire est la plus simple et pas du tout obligatoire. Il en revient au développeur de l adapter pour son propre problème. L adaptateur dynamique pourrait ressembler au code cité ci-présent : public class DynamicListViewAdapter extends BaseAdapter { private static final int TYPE_HEADER = 0 ; private static final int TYPE_BODY = 1 ; private static final int TYPE_MAX = 2 ; private List<Integer> mtypes = new ArrayList<Integer>(); 27

2 Fragmenter vos projets 28

2.2 ListFragment // Autres attributs @Override public int getviewtypecount() { return TYPE_MAX; @Override public int getitemviewtype(int position) { return mtypes.get(position); // Autres méthodes La mise en place est aussi simple que cela. Il faut aussi permettre de remplir la liste des types en les faisant correspondre avec les données. Comme le point précédent sur les listes personnalisées, il faut définir des méthodes pour attacher une liste de données à celle de l adaptateur et s occuper de la liste des types par la même occasion. Il en faudra deux : L une pour l en-tête et une seconde pour le corps de la liste. La première méthode prend en paramètre un modèle qui se trouve être une classe confectionnée spécialement pour cet exemple avec seulement deux attributs représentant une image et un texte ; La seconde est identique à la méthode du point précédent, elle prendra une liste d identifiants de chaînes de caractères. L implémentation de ces méthodes pourraient ressembler à : public class DynamicListViewAdapter extends BaseAdapter { // Autres attributs et méthodes public void bindheader(dynamiclistviewmodel model) { mmodelheader = model; mtypes.add(type_header); public void bindbody(list<integer> model) { mmodelbody = model; for (int i = 0 ; i < model.size(); i++) { mtypes.add(type_body); 2.2.3.2 Modification de l existant Ces ajouts ont des répercussions sur l implémentation des méthodes existantes. Le nombre de lignes et la ligne courante de la liste ne correspondent plus à une seule liste de données. Tout 29

2 Fragmenter vos projets comme la méthode d instanciation de la vue courante qui doit se charger d instancier la bonne vue. Les deux premières méthodes s implémentent assez facilement pour cet exemple : public class DynamicListViewAdapter extends BaseAdapter { // Autres attributs et méthodes @Override public int getcount() { if (mmodelheader == null) return mmodelbody.size(); return 1 + mmodelbody.size(); @Override public Object getitem(int position) { int type = getitemviewtype(position); return type == TYPE_HEADER? mmodelheader : mmodelbody.get(position - 1); // Autres méthodes La méthode public View getview(int position, View convertview, ViewGroup parent) est un poil plus complexe mais, au final, ne fait qu utiliser les autres méthodes de l adaptateur. Il faut récupérer le type de la ligne courante au début de la méthode pour pouvoir instancier la vue adéquate. Son implémentation est très similaire à la précédente, mise à part qu elle effectue une série de condition en fonction de ce type. @Override public View getview(int position, View convertview, ViewGroup parent) { View v = null ; int type = getitemviewtype(position); if (convertview == null) { switch (type) { case TYPE_HEADER: v = new DynamicHeaderListViewView(mContext); break ; case TYPE_BODY: v = new DynamicBodyListViewView(mContext); break ; else { switch (type) { case TYPE_HEADER: v = (DynamicHeaderListViewView) convertview; break ; case TYPE_BODY: v = (DynamicBodyListViewView) convertview; 30

2.3 Interfaces dynamiques break ; switch (type) { case TYPE_HEADER: DynamicListViewModel model1 = (DynamicListViewModel) getitem(position); ((DynamicHeaderListViewView) v).bind(model1.getimageressource(), model1.gettextressource()); break ; case TYPE_BODY: Integer model2 = (Integer) getitem(position); ((DynamicBodyListViewView) v).bind(model2); break ; return v; Il n en faut pas plus pour concevoir une liste dynamique. Tous les changements se situent au niveau de l adaptateur. Il suffit alors d intégrer ce nouvel adaptateur à l activité ou le fragment hôte en n oubliant pas d appeler les méthodes pour lier les données à la liste. Le résultat de l exemple ressemble à ceci : 2.2.4 En résumé ListFragment est une sous classe de Fragment qui contient automatiquement une ListView ; Il est possible d afficher une vue à l écran lorsqu il n y a aucun élément dans la liste. Cela grâce à un fichier XML d affichage attaché à une ListFragment ; Il est nécessaire de développer son propre adaptateur lorsque les vues, qui composent une liste, deviennent complexes ; Une liste dynamique oblige la redéfinition de deux méthodes supplémentaires dans son adaptateur : public int getviewtypecount() et public int getitemview- Type(int position). 2.3 Interfaces dynamiques La création des fragments est maintenant chose connue mais, jusqu à présent, ils ont été assimilés à l écran complet d un smartphone. Le promesse derrière ce concept est toute autre puisque son but est de dynamiser les interfaces à travers les différents appareils (qu ils soient smartphones, tablettes, télévisions ou autres). De brefs aperçus sur les possibilités, ont été donnés mais ni les bonnes pratiques ni la communication entre les fragments n ont été expliquées. 31

2 Fragmenter vos projets 32

2.3 Interfaces dynamiques 2.3.1 Concevoir une interface dynamique Concevoir une interface n est pas une chose aisée, surtout sur Android. Au vu de la diversité des écrans sur tous les types d appareils mobiles, il faut avant tout penser ses interfaces avant de les développer. Par exemple, un smartphone se contentera d afficher un fragment à la fois (qu il soit en paysage ou en portrait) alors qu une tablette pourrait afficher deux fragments en portrait et trois en paysage (encore faut-il savoir s il s agit d une tablette 7 ou 10 pouces). C est encore une autre histoire avec les télévisions mais le problème reste le même. En s imposant une limite aux smartphones et aux tablettes, peu importe leurs tailles, une pratique d ergonomie reconnue consiste a afficher un fragment sur smartphone et deux sur tablette en mode paysage. Cela permet de naviguer convenablement sur smartphone (comme toutes les applications) et de remplir complètement l écran d une tablette forcément plus grande. Figure 2.8 Deux fragments affichés dans différentes configurations L objectif est d ajouter un fragment à une activité pendant son exécution, dans les deux cas. Pour les smartphones, il faut changer le fragment visible à l écran. Pour les tablettes, charger les données nécessaires si une communication est à faire entre le fragment A et le fragment B. Par exemple, le fragment A pourrait être une liste de pays et le fragment B pourrait vouloir afficher son drapeau. Les deux fragments doivent communiquer et rester affichés à l écran. [[information]] Pour simplifier d avantage, l exemple d illustration ne fera aucune distinction entre les appareils. Les interfaces seront pensées en mode portrait et paysage à la place des tailles minimales. La manière de procéder est simple et requiert l utilisation de l API de gestion des fragments. Couplé à cela, la création des deux «layouts» du même nom pour déclarer l interface en mode portrait et paysage. Le but est d obtenir le résultat de l illustration précédente sans tenir compte du type d appareil. 2.3.2 Initialiser l activité hôte Pour illustrer la communication entre des fragments, il va falloir réviser quelques drapeaux européens. L idée est d afficher une liste de pays et son drapeau correspondant. Le projet nécessitera deux fragments : Un premier pour la liste des pays, un second pour le drapeau du pays sélectionné par l utilisateur. Le mode portrait affichera les fragments en plein écran en les remplaçant à la 33