Explorer les Livres électroniques
Catégories
Explorer les Livres audio
Catégories
Explorer les Magazines
Catégories
Explorer les Documents
Catégories
Android
Table des matières
Aller plus loin dans le développement Android
Fragment
Introduction aux fragments
Utiliser des fragments fixes
Utiliser des fragments dynamiques
ListFragment
Utilisation simple des listes
Intégrer une vue personnalisée
Vers des listes dynamiques
PreferenceFragment
Paramétriser son application
A iner ses paramètres avec les en-têtes
Lire les préférences
DialogFragment
Créer un DIalogFragment
Créer un AlertDialog
A icher une boite de dialogue
La barre d'action des applications
Intégrer un menu
Possibilités avancées
Menu contextuel
Slider à travers des écrans
Passer des informations à la création d'un fragment
Utilisation du widget ViewPager
Ajout d'un indicateur de la page
Notifier l'utilisateur
Basique
Les di érents styles
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Ajouter des boutons d'action
Le partage par NFC
Les di érents tags existants
Lecture d'un tag
Echange par Beam
La mise en place d'un serveur pour nous permettre d'alimenter nos applications par après.
La gestion de données partagées avec, entre autre, la récupération des données sur une base de données distantes.
L'intégration d'une Google Map de la génération de la clé API aux marqueurs à placer sur la map.
Si ce menu vous parait intéressant à suivre, attendez de lire le tutoriel et d'en apprendre plus.
Vous pouvez retrouver tous les codes sources de ce tutoriel sur ce projet GitHub.
Fragment
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Introduction aux fragments
Les fragments, kézako ?
La notion de fragment est souvent confuse pour les débutants et pas toujours bien comprise par ceux qui commencent à programmer assez régulièrement sur la
plateforme Android. Les fragments sont à mi-chemin entre l'activité et la vue ; c'est-à-dire qu'il ne s'agit ni de l'un, ni de l'autre mais qu'ils sont étroitement liés.
Votre fragment consiste à définir un morceau d'interface que vous pourrez attacher à plusieurs endroits, sur des activités.
Par exemple, dans le cas où vous désirez rendre compatible votre application sur smartphone et sur tablette, vous n'aurez pas spécialement envie avoir la même
interface. La taille d'écran des tablettes étant largement plus grande que celles des smartphones, il serait dommage de ne pas en profiter. L'idée consiste de
définir des fragments que vous a icherez un à un sur un smartphone et à plusieurs sur tablette.
Si vous avez une liste de news (par hasard ? :-° ). Sur votre smartphone, vous a icherez cette liste et une fois que l'utilisateur aura e ectué une pression sur l'un
des items de la liste, vous lancerez un autre écran avec les détails de la news sélectionnée. Quant à la version tablette, vous a icherez la liste des news à gauche et
directement à droite les détails de la news sélectionnée, sans changer d'écran.
Cependant, il en rajoute quand même qui sont appelés par l'activité hôte du fragment. Nous verrons l'utilité de ces nouvelles méthodes dans la suite de ce
chapitre. Vous pouvez voir l'ensemble des méthodes via le schéma ci-dessous disponible sur le portail des développeurs Android.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Cycle de vie des fragments disponible à partir du site des développeurs Android
La bibliothèque de compatibilité
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
C'est bien beau n'est-ce pas ? Un monde où vous pouvez librement placer des fragments aux endroits que vous désirez pour optimiser vos applications sur le plus
d'appareil possible. Malheureusement, ce n'est pas si simple. Au début, Android était dédié uniquement aux smartphones ; c'est-à-dire à des écrans de moins de 4
pouces (les smartphones de plus de 4 pouces ne sont arrivés que très récemment à l'heure où j'écris ces lignes). Par après, Google a étendu son système aux
tablettes avec la version 3 (les versions 2 et moins étaient donc destinés aux smartphones) et la version 4 qui unifie les 2 types.
Aujourd'hui, on commence de plus en plus à voir des TV avec Android comme système. Il est tout à fait possible de développer pour ce genre d'appareil
mais les bonnes pratiques d'ergonomie sont encore un peu vague. C'est pourquoi nous ne verrons pas d'exemple concret pour les TV mais les techniques
que vous apprendrez dans ce tutoriel vous permettront d'en développer.
C'est avec cette version 3, HoneyComb, qu'est apparu les fragments. Techniquement, ce composant (et les autres que nous verrons dans la suite de cette première
partie) n'est pas disponible en dessous de cette version. Comment pouvons-nous donc développer notre application sans devoir créer deux projets (un pour les
versions 2 et antérieur et un autre pour la version 3 et supérieur) ?
Je vous ai déjà dit que Google était une boite formidable ? Maintenant, je vous le dis. Google est une boite formidable ! Ils ont développé une librairie de
compatibilité qui vous permettra d'utiliser une très grande partie des fonctionnalités disponibles à partir de la version 3 d'Android dès la version 2.1. Soit
regrouper environ 95% du marché des appareils tournant avec Android. Nous apprendrons à l'utiliser et à aller plus loin grâce à un projet communautaire de
compatibilité que nous verrons plus loin dans ce tutoriel.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
avez délimité dans le manifest de votre projet ; c'est-à-dire que vous n'aurez pas accès à cet import si vous n'êtes pas à une version 3 et plus puisque Android 2 ne
connait normalement pas les fragments. Le deuxième redirige vers le Fragment du projet de compatibilité Google (bibliothèque inclut automatiquement lors de
la création d'un nouveau projet dans les récents ADT). Sauf si vous ne désirez pas rendre vos futurs programmes compatibles avec les anciens terminaux, nous
utiliserons à chaque fois les imports de la bibliothèque de compatibilité.
Il faudra constamment faire attention aux imports dans vos projets. C'est une erreur commune chez les développeurs débutants mais aussi expérimentés.
Google a tenté de rendre l'utilisation de la bibliothèque le plus proche de son utilisation normal. Mise à part quelques méthodes, elles auront globalement
les mêmes signatures.
Pour notre exemple, nous allons faire quelque chose de simple. Nous allons simplement placer un TextView au centre du fichier XML d'a ichage que nous
attacherons à un Fragment qui sera lui même attaché à une Activity . Nous allons nommer notre fichier XML d'a ichage fragment_fixe et nous placerons
dedans :
<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>
Nous désérialisons ce fichier XML d'a ichage dans un fragment que nous nommerons FixeFragment :
package com.siteduzero.android.fragments.fixe;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
import android.view.View;
import android.view.ViewGroup;
import com.siteduzero.android.R;
Vous remarquerez que je spécifie exprès la définition du paquetage et les imports. C'est une chose importante dans les fragments, cela sera une habitude
prise dans ce tutoriel pour que vous ne soyez jamais perdu.
Vous pouvez vous rendre compte de la simplicité déconcertante de la création d'un fragment. Son utilisation est tout aussi simple lorsque vous l'attachez
fixement à une activité. Dans chaque activité, nous allons créer un autre fichier XML d'a ichage, que nous nommerons activity_fragment_fixe, et dans lequel
nous allons déclarer un widget Fragment qui spécifie dans son attribut android:name notre FixeFragment.
Dans le code de l'activité, FixeActivity, il nous su it simplement de désérialiser le fichier XML d'a ichage que nous venons de créer pour attacher notre
Fragment et d'étendre la classe FragmentActivity à la place de Activity pour notifier Android que nous utilisons des Fragment .
package com.siteduzero.android.fragments.fixe;
import com.siteduzero.android.R;
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
Qu'est ce que nous pouvons en dire ? Vous pouvez vous rendre compte que l'activité est vide, peu importe ce que vous placez dans un fragment. 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'application). Dans notre cas, les fragments joueront le rôle de contrôleurs pour les vues qu'ils instancient. Cela permet
de maintenir plus aisément le code et de séparer les responsabilités entre di érentes classes.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Résultat de l'exécution de l'activité FixeActivity
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Résultat de l'exécution de l'activité FixeActivity en paysage
Correction
Vous avez réussi à trouver quelque chose ? Si vous êtes parvenu à un résultat similaire au mien, c'est déjà pas mal. Si vous avez la même solution que moi, c'est
encore mieux. Pourquoi ? Simplement parce que la solution la plus simple pour parvenir à mon résultat est de créer un nouveau fichier XML d'a ichage du même
nom que celui de l'activité qui se trouve dans le dossier layout mais dans le layout-land et en définissant les deux Fragment dans ce fichier. Le système se rendra
automatiquement dans ce dossier pour récupérer le bon fichier XML et tout sera fait automatiquement !
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
android:layout_height="match_parent"
android:orientation="horizontal" >
<fragment
android:name="com.siteduzero.android.fragments.fixe.FixeFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<fragment
android:name="com.siteduzero.android.fragments.fixe.FixeFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
Utiliser ces services est très simple mais il ne faut pas oublier que nous utilisons la bibliothèque de compatibilité de Google. L'initialisation du manager est donc
un peu di érente. Vous aurez sans doute remarqué le mot clé "support" dans l'importation de la classe Fragment . Ce mot clé n'est pas un hasard et se
retrouvera un peu partout dans l'utilisation des classes venant de la bibliothèque. Ainsi, pour initialiser, vous utiliserez non pas la méthode
public FragmentManager getFragmentManager() mais la méthode public FragmentManager getSupportFragmentManager() .
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Si vous utilisez des fragments qui viennent du paquetage android.app.Fragment mais que vous utilisez FragmentManager de la bibliothèque de
compatibilité (ou inversement), vous aurez une erreur. Vous êtes obligé de faire un choix !
Le réel changement sera dans notre activité, DynamicActivity . Première chose, son fichier XML d'a ichage ne comportera aucun fragment mais un
FrameLayout . Il servira de conteneur pour nos fragments. Vous comprendrez bien assez vite. Sachez simplement que vous devrez lui donner un identifiant afin
de pouvoir remplacer son contenu par un autre.
Seconde chose, nous allons devoir structurer notre code. A partir de la méthode public void onCreate(Bundle savedInstanceState) , nous appelerons
deux méthodes : private void setupFragments() et private void showFragment(final Fragment fragment) . La première méthode initialisera les
di érents fragments et ne sera appelé qu'à partir de la méthode onCreate. La seconde méthode se chargera d'a icher le fragment qu'on passe en paramètre à
l'écran. Elle pourra être appelé à partir des boutons.
this.mDynamic1Fragment = (Dynamic1Fragment) fm
.findFragmentByTag(Dynamic1Fragment.TAG);
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
if (this.mDynamic1Fragment == null) {
this.mDynamic1Fragment = new Dynamic1Fragment();
}
this.mDynamic2Fragment = (Dynamic2Fragment) fm
.findFragmentByTag(Dynamic2Fragment.TAG);
if (this.mDynamic2Fragment == null) {
this.mDynamic2Fragment = new Dynamic2Fragment();
}
}
ft.replace(R.id.frameLayoutListView, fragment);
ft.commit();
}
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Chaque transaction doit appeler la méthode commit() pour voir ses opérations s'e ectuer. En cas contraire, aucune erreur ne sera lancée mais rien ne se
passera.
Résultat final
Mais attends une seconde. C'est bien beau tout ça mais je fais comment pour appeler la méthode
private void showFragment(final Fragment fragment) lorsque je clique sur mes boutons ? Mes fragments ne connaissent pas forcément l'activité
précise dans lequel il se trouve.
Vous n'avez pas tord mais Google a apporté une réponse à ce léger problème. L'un des attributs que vous pouvez donner à vos boutons est le suivant :
android:onClick . La valeur que vous donnez à cet attribut vous oblige à implémenter une méthode du même nom dans l'activité dans laquelle il est
désérialisé. Du coup, dans le fichier XML d'a ichage de fragment 1 et 2, nous avons donné les valeurs respective goToFragment2 et goToFragment1. Par
conséquent, nous implémentons notre activité de la manière suivante :
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment_dynamic);
mFragment = getIntent().getStringExtra("fragment");
setupFragments();
if (mFragment.equals("Dynamic1Fragment")) {
showFragment(this.mDynamic1Fragment);
} else if (mFragment.equals("Dynamic2Fragment")) {
showFragment(this.mDynamic2Fragment);
}
}
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
private void setupFragments() {
final FragmentManager fm = getSupportFragmentManager();
this.mDynamic1Fragment = (Dynamic1Fragment) fm
.findFragmentByTag(Dynamic1Fragment.TAG);
if (this.mDynamic1Fragment == null) {
this.mDynamic1Fragment = new Dynamic1Fragment();
}
this.mDynamic2Fragment = (Dynamic2Fragment) fm
.findFragmentByTag(Dynamic2Fragment.TAG);
if (this.mDynamic2Fragment == null) {
this.mDynamic2Fragment = new Dynamic2Fragment();
}
}
ft.replace(R.id.frameLayoutListView, fragment);
ft.commit();
}
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
}
Si vous exécutez notre application, lorsque vous cliquez sur l'un des boutons des fragments, le fragment courant s'animera en se déplaçant vers la droite pour
laisser place à notre second fragment. Vous constatez qu'en plus de pouvoir facilement de fragment, il est simple d'e ectuer quelques animations sur le
changement.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Résultat de l'exécution de l'activité DynamicActivity
Correction
package com.siteduzero.android.fragments.dynamic;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
import com.siteduzero.android.R;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment_dynamic);
if (savedInstanceState != null)
mFragment = savedInstanceState.getString("fragment");
else
mFragment = getIntent().getStringExtra("fragment");
setupFragments();
if (mFragment != null) {
if (mFragment.equals("Dynamic1Fragment")) {
showFragment(this.mDynamic1Fragment);
} else if (mFragment.equals("Dynamic2Fragment")) {
showFragment(this.mDynamic2Fragment);
}
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("fragment", mFragment != null ? mFragment : "");
super.onSaveInstanceState(outState);
}
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
private void setupFragments() {
final FragmentManager fm = getSupportFragmentManager();
this.mDynamic1Fragment = (Dynamic1Fragment) fm
.findFragmentByTag(Dynamic1Fragment.TAG);
if (this.mDynamic1Fragment == null) {
this.mDynamic1Fragment = new Dynamic1Fragment();
}
this.mDynamic2Fragment = (Dynamic2Fragment) fm
.findFragmentByTag(Dynamic2Fragment.TAG);
if (this.mDynamic2Fragment == null) {
this.mDynamic2Fragment = new Dynamic2Fragment();
}
}
ft.replace(R.id.frameLayoutListView, fragment);
ft.commit();
}
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
}
ListFragment
Le widget ListView est sans aucun doute l'un des composants graphiques les plus utilisés dans les applications Android, au même titre que le
ViewPager ou le GridView . Il permet d'a icher facilement des informations l'un à la suite de l'autre verticalement avec des vues personnalisées ou non.
Dans un premier temps, nous allons voir comment utiliser ce composant mêlé à la puissance des fragments. Nous compliquerons rapidement les choses en
intégrant des vues personnalisées à chaque item de nos listes. Pour finir, nous rendrons l'a ichage de cette liste dynamique avec l'apparition de vues
di érentes.
Cependant, nous reviendrons plus en détail sur les adaptateurs que vous devez créer lorsque vous en créez un vous même. Il existe une manière simple et e icace
de gérer le cycle de vie des vues qu'ils gèrent mais trop peu connue de certains développeurs. Bien entendu, l'adaptation aux fragments sera un point important
de ce chapitre et l'utilisation, parfois méconnue, de certaines choses pour rendre vos applications plus agréable.
Ce que nous allons faire consiste à déclarer une liste lorsqu'il y aura des éléments à a icher ou du texte pour indiquer à l'utilisateur que la liste est vide. Pour nous
permettre d'arriver à ce résultat, nous allons nous servir des « id » que le framework Android met à disposition des développeurs. En e et, il existe deux
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
identifiants un peu spéciaux contenu dans @android:id . Il donne accès soit à list soit à empty . Il permettra d'indiquer à Android le composant à a icher
lorsqu'il y a une raison d'a icher une liste ou lorsqu'il n'y a rien dedans.
Dans notre exemple, nous avons choisi d'a icher que du texte mais cela peut être infiniment plus complet. Vous pourriez vouloir a icher une image et du
texte en dessous. Dans ce cas là, il vous faudra mettre votre image et votre texte dans un layout que vous identifierez par la valeur empty .
Si nous restons simple, le fichier XML ressemblera à quelque chose comme ceci :
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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>
Création de la ListFragment
A la di érence du chapitre précédent, notre fragment ne va pas étendre la classe Fragment mais ListFragment qui est le parfait équivalent de la classe
ListActivity . De la même manière que les fragments basiques, nous allons désérialiser notre fichier XML d'a ichage dans sa méthode
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) (chose qui n'est pas obligatoire. Vous
pouvez ne pas vouloir a icher quelque chose lorsque la liste est vide. Dans ce cas, il vous su it de ne créer aucun fichier XML et de ne pas redéfinir la méthode
précédemment citée).
De la même manière qu'une ListActivity , nous devons récupérer notre liste pour lui attacher un adaptateur (que nous ne créerons pas pour le moment).
L'unique subtilité dans ce cas présent est la méthode à redéfinir. En e et, nous aurons accès à notre liste qu'une fois l'activité dans laquelle le fragment est
hébergé sera construite. Nous faisons toutes les manipulations destinées à la gestion de la liste dans la méthode
public void onActivityCreated(Bundle savedInstanceState) .
package com.siteduzero.android.lists;
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;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_listview, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
String[] items = getResources().getStringArray(R.array.list_examples);
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Résultat de l'exécution d'une liste simple
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
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>
Pour rester simple, notre classe Java, qui va désérialiser notre fichier XML d'a ichage, redéfiniera simplement les constructeurs nécessaires pour appeler la super
classe ( LinearLayout ) et o rira une méthode à notre adaptateur pour attacher du texte à notre TextView .
package com.siteduzero.android.lists;
import com.siteduzero.android.R;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;
import android.widget.TextView;
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
public CustomListViewView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
Vous devriez être capable de concevoir cet adaptateur seul. C'est pourquoi je vous laisse y réfléchir (et je vous conseil de le faire pour bien progresser). Après quoi,
je vous invite à consulter ma solution (que vous retrouverez cacher ci-dessous) pour vous corrigez.
package com.siteduzero.android.lists;
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
@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) {
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
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
else {
v = (CustomListViewView) convertView;
}
v.bind(getItem(position));
return v;
}
Notre fragment sera exactement identique au précédent sous-chapitre à l'exception près que nous n'utilisons plus ArrayAdapter mais notre propre adaptateur
( CustomListViewAdapter dans mon cas). Vous devriez alors avoir le même résultat que moi avec une belle fluidité puisque notre adaptateur est optimisé au
niveau de la gestion de la mémoire.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Résultat de l'exécution d'une liste avec une vue personnalisée
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
forme. Android a pensé à ce cas et nous permet facilement d'a icher plusieurs vues personnalisées en fonction de nos désirs.
Modification de l'adaptateur
Le but de notre nouveau adaptateur est de construire plusieurs types de vues avec une seule méthode (je vous laisse deviner laquelle ;) ). Pour cet exemple, nous
construisons deux vues que je nommerai DynamicHeaderListViewView et DynamicBodyListViewView. La première a iche une image à gauche et du texte à
droite, la seconde a iche simplement du texte (comme la vue pour le sous-chapitre précédent). Je vous laisse le bon soin de créer ses vues comme nous l'avons
fait précédemment. Cela ne devrait pas vous posez de problème.
Le véritable changement se situe au niveau de notre adaptateur. Nous étendrons toujours BaseAdapter mais nous allons redéfinir deux méthodes
supplémentaires qui sont facultatives (j'entends par là qu'il n'est pas nécessaire de toujours les redéfinir, seulement quand cela est nécessaire) :
public int getViewTypeCount() et public int getItemViewType(int position) . A quoi servent ces méthodes ?
La première nous demande combien de vues di érentes seront présentes dans notre liste.
La seconde nous demande le type de vues pour la position courante dans la liste.
Pour pouvoir compléter ces méthodes, nous aurons besoin de constantes représentants les types de vues et une liste faisant correspondre chaque ligne de la liste
avec son type associé. Si nous continuons notre exemple, avec le « header » et le « body », nous aurons quelque chose qui ressemble à ceci :
// Autres attributs
@Override
public int getViewTypeCount() {
return TYPE_MAX;
}
@Override
public int getItemViewType(int position) {
return mTypes.get(position);
}
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
// Autres méthodes
}
La mise en place est aussi simple que cela. Il va maintenant falloir remplir la liste des types avec les lignes de la liste. Cela se fait naturellement dans les méthodes
d'attachement. Nous en aurons deux : l'une pour l'en-tête de la liste 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é par mes soins avec seulement 2 attributs représentant une image et un texte. La seconde méthode est identique à la
méthode vue au sous-chapitre précédent, elle prendra une liste de chaînes de caractères. Pour chacune de ces méthodes, nous ajouterons au fur et à mesure les
types dans la liste des types. Cela nous dera quelque chose comme ceci :
Nous avons aussi besoin de retoucher un peu nos anciennes méthodes. La taille de notre liste ne correspond plus à la taille de notre liste de données. Il faut donc
prévoir qu'un en-tête (ou pas) soit placé quelque part dans notre liste. Ainsi, nous modifions nos méthodes de la manière suivante :
@Override
public int getCount() {
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
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
}
Pour finir, nous avons notre méthode public View getView(int position, View convertView, ViewGroup parent) sur laquelle je vais vous laisser
cogiter. Vous disposez de toutes les méthodes nécessaires pour mener à bien sa confection. Si vous avez bien compris l'exemple précédent avec une seule vue
personnalisée pour toute la liste, vous ne devriez pas avoir de mal à en faire de même pour plusieurs vues personnalisées. Pensez simplement que les méthodes
que nous avons redéfinies ne sont sans doute pas là pour rien. Bien sûr, ma solution se trouve cachée ci-dessous.
package com.siteduzero.android.lists;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
private List<Integer> mTypes = new ArrayList<Integer>();
private DynamicListViewModel mModelHeader = null;
private List<Integer> mModelBody = new ArrayList<Integer>();
private Context mContext;
@Override
public int getViewTypeCount() {
return TYPE_MAX;
}
@Override
public int getItemViewType(int position) {
return mTypes.get(position);
}
@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);
}
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
@Override
public long getItemId(int position) {
return position;
}
@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;
break;
}
}
switch (type) {
case TYPE_HEADER:
DynamicListViewModel model1 = (DynamicListViewModel) getItem(position);
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
((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. Il vous su it ensuite d'intégrer ce nouvel adaptateur à votre activité, en n'oubliant pas d'appeler les
méthodes d'attachement pour remplir votre liste et vous devriez obtenir un résultat similaire au mien :
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Résultat de l'exécution d'une liste avec plusieurs vues personnalisées
PreferenceFragment
Depuis la version 3, Android met à disposition des développeurs des outils permettant de paramétriser facilement son application. En quoi consiste cette
paramétrisation ? C'est simple. Il s'agit ni plus ni moins que des données partagées dans toute l'application (que vous avez déjà certainement utilisé) mais
intégrer dans une conception toute fait. Nous confectionnerons des fragments (ou des activités) qui auront comme seul objectif l'a ichage des paramètres
de la même manière que ceux de votre smartphone.
Cela va vous facilitez la vie mais je vous met en garde sur une petite chose. Nous utilisons depuis le début de ce tutoriel la bibliothèque de compatibilité
développé par Google. Les préférences ont également été intégrées dans cette bibliothèque mais n'est pas très performante (ou du moins, pas à une grande
échelle). Parce que le code est quand même assez di érent et pour ne pas être limité, nous ne l'utiliserons pas pour ce chapitre. Mais sachez qu'il est
possible de l'utiliser. Il faudra juste se renseigner un peu sur la façon de s'y prendre.
PreferenceCategory doit contenir les attributs android:key et android:title pour pouvoir l'identifier et lui donner un titre.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Il existe plusieurs types de préférence. Avant tout, notez que vous devrez toujours donner une valeur aux attributs suivants : android:key pour pouvoir
identifier les préférences et en récupérer sa valeur par la mémoire partagée, android:title pour donner un nom à la préférence, android:summary pour
donner des précisions supplémentaires sur la préférence et android:defaultValue pour donner une valeur par défaut à la préférence. On retrouvera :
RingtonePreference pour saisir une sonnerie à partir de votre terminal ou d'une application qui vous permet d'en télécharger.
Preference qui est une valeur non éditable par l'utilisateur. Cette préférence change par une autre préférence. Raison pour laquelle vous devez déclarer
l'attribut android:dependency qui contiendra, comme valeur, la clé d'une autre préférence.
ListPreference est un peu spécial. Vous devez définir une liste de valeur dans lequel l'utilisateur pourra faire son choix. Pour ce faire, c'est simple. Il faut
donner une valeur pour deux nouveaux attributs : android:entries pour donner un tableau de valeur qui sera a iché à l'utilisateur et
android:entryValues pour a icher le code des valeurs de chaque ligne de ce tableau.
Pour vous aidez à mieux comprendre, ci-dessous se trouve un exemple complet pour définir ses préférences reprenant toutes les notions que nous avons vu juste
avant.
<PreferenceCategory
android:key="pref_key_category_1"
android:title="@string/title_category_1" >
<CheckBoxPreference
android:defaultValue="false"
android:key="pref_key_pref_1"
android:summary="@string/summary_pref_1"
android:title="@string/title_pref_1" />
<Preference
android:dependency="pref_key_pref_1"
android:key="pref_key_pref_2"
android:summary="@string/summary_pref_2"
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
android:title="@string/title_pref_2" />
<SwitchPreference
android:key="pref_key_pref_3"
android:summary="@string/summary_pref_3"
android:switchTextOff="@string/switch_off_pref_3"
android:switchTextOn="@string/switch_on_pref_3"
android:title="@string/title_pref_3" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_key_category_2"
android:title="@string/title_category_2" >
<EditTextPreference
android:key="pref_key_pref_4"
android:summary="@string/summary_pref_4"
android:title="@string/title_pref_4" />
<ListPreference
android:entries="@array/list_pref_5"
android:entryValues="@array/list_pref_5"
android:key="pref_key_pref_5"
android:summary="@string/summary_pref_5"
android:title="@string/title_pref_5" />
<RingtonePreference
android:key="pref_key_pref_6"
android:ringtoneType="ringtone"
android:summary="@string/summary_pref_6"
android:title="@string/title_pref_6" />
</PreferenceCategory>
</PreferenceScreen>
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
A ichage des paramètres
package com.siteduzero.android.settings;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import com.siteduzero.android.R;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
A iner ses paramètres avec les en-têtes
Tout comme les catégories, les en-têtes ont pour objectif de rassembler des préférences et de les structurer mais à plus grande échelle. Une petite application
aura rarement besoin d'utiliser le concept que je vais vous enseigner maintenant mais c'est une bonne chose à connaitre parce que vous n'aurez peut-être pas
toujours des petites applications à développer. En fait, vous avez déjà vu plusieurs fois des en-têtes. L'écran des paramètres de votre smartphone utilise les en-
têtes simplement pour structurer la très grande quantité de chose à pouvoir paramétrer.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
A ichage des paramètres du smartphone
Après cela, il su it de déclarer autant d'élèment header que vous voulez d'en-tête. Celui-ci peut et doit déclarer remplir certains attributs :
Un exemple simple exemple concret se trouve ci-dessous avec son résultat à l'exécution de l'application.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Résultat de l'exécution des en-têtes
package com.siteduzero.android.settings;
import java.util.List;
import android.preference.PreferenceActivity;
import com.siteduzero.android.R;
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
public abstract Object getSystemService(String name) pour récupérer le manager dont vous avez besoin pour faire des manipulations sur une
certaine fonctionnalité ? Et bien, malheureusement pour vous, ce n'est pas la même chose cette fois-ci ! :p
En fait, c'est encore plus simple. Le manager est PreferenceManager et pour l'initialiser, vous aurez besoin d'appeler la méthode static
public static SharedPreferences getDefaultSharedPreferences(Context context) qui renvoi un SharedPreferences (chose que vous devrez
connaître). A partir de là, vous pourrez appeler des getters pour récupérer les valeurs de vos préférences à partir des clés que vous avez donné.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
A ichage des valeurs des paramètres
DialogFragment
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Nous allons aborder la dernière notion utilisant les fragments à partir de la version 3 d'Android, les DialogFragment . Ce composant nous permettra
d'a icher une boite de dialogue à l'utilisateur de manière beaucoup plus souple et plus complet que vous auriez pu le faire avec les anciens composants des
versions inférieurs à la 3.
Créer un DIalogFragment
Vous avez sans doute déjà utiliser des AlertDialog ou des Dialog (surtout si vous avez lu le tutoriel d'Applidore). L'idée est de ré-utiliser ce type de
composant mais en lui attachant des fragments. C'est une pratique qui vous permettra de concevoir des boites de dialogue infiniment plus complexe et plus
puissante que vos anciennes boites de dialogue.
DialogFragment servira de conteneur à notre fragment pour le transformer en boite de dialogue et ainsi fournir le style et la structure de la boite. Cette classe
fournit tous les contrôles nécessaires pour créer la boite et gérer son apparence. Chose que nous apprendrons à faire tout au long de ce chapitre ainsi que
l'intégration de builder pour un autre type de boite. :)
Pour commencer, nous allons procéder comme à chaque création d'un type de fragment ; c'est-à-dire que nous allons étendre notre classe à DialogFragment
et redéfinir un certains nombre de méthodes utiles à l'intégration de notre fragment dans la boite et à sa gestion. Pour ce faire, nous allons redéfinir et définir les 2
méthodes suivantes :
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) : Pour désérialiser le fichier XML
représentant notre fragment et pour donner un titre à notre boite de dialogue (ce dernier étant optionnel).
public static MyDialogFragment newInstance() : Je reviendrais dans la seconde partie de ce tutoriel sur ce type de méthode mais sachez qu'elle
nous permet d'encapsuler la création de notre fragment et d'en connaitre des potentielles données. Ne vous tracassez pas la tête avec ça maintenant, vous
comprendrez bien assez tôt son utilité.
package com.siteduzero.android.dialog;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
import com.siteduzero.android.R;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_dialog, container, false);
getDialog().setTitle(getArguments().getInt("title"));
return v;
}
}
Chez moi (vous n'aurez pas le même résultat si le fichier XML est di érent), le résultat final intégré dans une FragmentActivity donnera le résultat suivant :
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Résultat de l'exécution des boîtes de dialogue DialogFragment
Créer un AlertDialog
Vous êtes censé savoir comment créer un AlertDialog . Je ne rentrerais donc pas dans les détails en ce qui concerne sa création mais beaucoup plus en ce qui
concerne son intégration dans un fragment. En fait, c'est vraiment très semblable au DialogFragment et vous devrez avoir une petite idée de la manière de s'y
prendre avec les connaissances que je viens de vous enseigner et vos connaissances précédentes sur sa simple création dans une Activity .
Bien entendu, ce n'est pas exactement la même chose. Nous n'allons pas devoir redéfinir la méthode
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) mais
public Dialog onCreateDialog(Bundle savedInstanceState) . A partir de là, il nous su it de retourner une AlertDialog avec l'aide d'un builder.
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int title = getArguments().getInt("title");
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
((DialogActivity) getActivity())
.doPositiveClick();
}
}).create();
}
N'oubliez pas d'implémenter la méthode static pour créer une instance comme nous l'avons fait avec DialogFragment .
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Résultat de l'exécution des boîtes de dialogue AlertDialog
public void doNegativeClick() : Appelé lorsqu'on clique sur le bouton négatif de l' AlertDialog .
public void doPositiveClick() : Appelé lorsqu'on clique sur le bouton positif de l'AlertDialog .
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
public void showAlertDialog(View v) : Appelé au clique de l'utilisateur sur le bouton de notre activité destiné à l'a ichage de l' AlertDialog .
public void showDialogFragment(View v) : Appelé au clique de l'utilisateur sur le bouton de notre activité destiné à l'a ichage de DialogFragment .
protected void showDialogType(int type) : Pour switcher dynamiquement entre les di érentes boîtes de dialogue.
Je vous laisse à vos lignes de codes. Vous trouverez ma solution et son résultat à la suite de ce chapitre.
Correction
package com.siteduzero.android.dialog;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import com.siteduzero.android.R;
import com.siteduzero.android.dialog.alert.MyAlertDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dialog);
}
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
}
}
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Résultat de l'exécution de l'activité pour a icher nos boîtes de dialogue
Intégrer un menu
J'ai une bonne nouvelle pour vous, intégrer un menu dans une barre d'action est extrêmement simple. Comme vous êtes censé savoir comment créer des menus
(sinon, je vous renvoie sur le tutoriel d'Apollidore sur les gestion des menus), il nous faudra que quelques modifications à faire dans le fichier XML, c'est tout ! En
e et, le système détectera automatiquement que vous lancez votre application sur un système avec une version 3 ou supérieur d'Android et l'intègrera par défaut.
C'est plutôt pratique !
Voici ce que nous allons faire : Nous allons créer un menu avec 4 items qui auront un identifiant, un titre et une icone. Cependant, nous allons rajouter une notion
très importante dans ces nouveaux menus, son a ichage. En e et, un nouvel attribut est utilisable dans ces menus android:showAsAction . Cet attribut peut
prendre une ou plusieurs valeurs parmi cette liste :
ifRoom : A ichera l'item dans la barre d'action uniquement s'il y a encore de la place.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
never : N'a ichera jamais l'item dans la barre d'action.
always : A ichera l'item dans la barre d'action dans tous les cas.
collapseActionView : Nous reviendrons sur cet attribut un peu plus tard dans ce chapitre.
Vous devez savoir qu'il est possible de sélectionner plusieurs des valeurs grâce au pipeline « | ». Bien entendu, ne lui demander pas l'impossible, par exemple :
never|always.
Un exemple d'utilisation tout simple de nos 4 items se trouve à la suite :
<item
android:id="@+id/menu_search"
android:actionViewClass="android.widget.SearchView"
android:icon="@android:drawable/ic_menu_search"
android:showAsAction="always"
android:title="@string/menu_search"/>
<item
android:id="@+id/menu_add"
android:icon="@android:drawable/ic_menu_add"
android:showAsAction="ifRoom|withText"
android:title="@string/menu_add"/>
<item
android:id="@+id/menu_save"
android:icon="@android:drawable/ic_menu_save"
android:showAsAction="ifRoom|withText"
android:title="@string/menu_save"/>
<item
android:id="@+id/menu_crop"
android:icon="@android:drawable/ic_menu_crop"
android:showAsAction="never"
android:title="@string/menu_crop"/>
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
</menu>
Nous a icherons donc dans tous les cas le menu de recherche, s'il y a de la place et avec son texte le menu d'ajout et de sauvegarde et nous n'a icherons jamais
le redimensionnement dans la barre d'action mais dans un menu à part qui s'a ichera à l'extrème droite de la barre.
Du côté Java, rien ne change ! Vous continuez à redéfinir la méthode public boolean onCreateOptionsMenu(Menu menu) pour désérialiser votre menu et
public boolean onOptionsItemSelected(MenuItem item) pour réagir au clique sur l'un ou l'autre item du menu. Ceci nous donnera alors le résultat
suivant :
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
A ichage des items du menu
Comme vous pouvez le constater, Android a iche notre item de recherche et d'ajout mais comme il n'y a plus de place pour la sauvegarde, il le place dans le sous
menu accesible à l'extrème droite de la barre.
Possibilités avancées
La barre d'action, c'est sympa mais il est possible d'aller encore plus loin dans son utilisation. Nous ne verrons pas comment customiser cette barre. Cela
prendrait un nouveau chapitre entier à ce sujet et le design n'est pas le but de ce tutoriel. Cependant, si vous êtes curieux à ce sujet, Google a mis en place un site
accessible via ce lien qui vous permettra de générer des styles tout faits. Il su it alors de les intégrer à vos projets. Vous devriez avoir les compétences pour le faire
tout seul.
Barre de recherche
Dans un premier temps, nous allons voir comment rendre notre item, destiné à e ectuer une recherche, mieux intégré à notre barre d'action (et ainsi comprendre
à quoi servira la dernière valeur du nouvel attribut sur les items du menu). L'idée est la suivante : Lorsque nous cliquerons sur la loupe, un champ de recherche
prendra toute la place de la barre d'action (cachant les autres items du menu au passage) et a ichant le clavier pour permettre à l'utilisateur d'e ectuer sa
recherche dans votre application.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Pour ce faire, nous aurons besoin d'e ectuer des changements à la fois du côté de l'XML et du côté Java. Du côté XML, nous allons rajouter un nouvel attribut
android:actionViewClass . Il nous permet de spécifier un layout ou un widget à utiliser. Dans notre cas, nous allons utiliser un widget déjà integré au système
que nous ré-utilisons. Nous modifions aussi android:showAsAction en rajoutant la valeur collapseActionView pour rendre notre vue « pliable » dans l'item du
menu et ainsi la dépliée tout le long de notre barre lorsque nous cliquons dessus. Ainsi, nous obtenons :
<item
android:id="@+id/menu_search"
android:actionViewClass="android.widget.SearchView"
android:icon="@android:drawable/ic_menu_search"
android:showAsAction="ifRoom|collapseActionView"
android:title="@string/menu_search"/>
La modification du côté Java n'est pas nécessaire puisque si vous testez l'application comme ça, vous aurez l'e et escompté. Cependant, il est fort utile de
connaitre un listener qui s'attache à ce type de vue OnQueryTextListener . Ce listener vous demandera d'implémenter deux méthodes :
public boolean onQueryTextSubmit(String query) pour récupérer la chaîne de caractère que l'utilisateur aura rentré lorsqu'il aura envoyé la requête.
public boolean onQueryTextChange(String newText) pour récupérer la chaîne de caractère en cours lorsque l'utilisateur rentre un nouveau caractère
ou en supprime.
Ainsi, nous devons récupérer notre item lors de la désérialisation de notre menu et lui attacher notre listener via sa méthode
public void setOnQueryTextListener (SearchView.OnQueryTextListener listener) . Vous obtiendrez un résultat similaire à celui-ci :
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_actionbar, menu);
// SearchView
MenuItem itemSearch = menu.findItem(R.id.menu_search);
mSearchView = (SearchView) itemSearch.getActionView();
mSearchView.setOnQueryTextListener(new OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Toast.makeText(getApplicationContext(),
R.string.toast_search_submit, Toast.LENGTH_SHORT)
.show();
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
return true;
}
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
A ichage de la barre de recherche dans la barre d'action
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
n'importe quoi d'autres qu'un Intent supporte (image, fichier, etc.). Nous obtenons alors la méthode suivante :
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_actionbar, menu);
// ShareActionProvider
MenuItem itemProvider = menu.findItem(R.id.menu_share);
mShareActionProvider = (ShareActionProvider) itemProvider.getActionProvider();
return true;
}
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
A ichage des fournisseurs de partage
« Spliter » le menu
Vous savez sans doute de quoi je parle, l'application de messagerie du système Android l'utilise dans son application. L'idée est de séparer le menu de la barre
d'action dans une nouvelle barre situé en bas de l'écran. Cela nous permettra de mettre plus d'item visible à l'utilisateur et de dissocier la barre d'action du menu.
En contre partie, nous perdons de la place sur l'écran.
Sa mise en place est extrêmement simple puisqu'il su it de rajouter l'attribut et la valeur android:uiOptions="splitActionBarWhenNarrow" dans l'activité
contenant le menu que vous voulez diviser dans le fichier Manifest.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
A ichage de la division du menu à la barre d'action
Bouton home
Dernière petite chose, l'icone en haut à gauche de votre écran peut également servir comme un bouton. Il est généralement utilisé pour revenir en arrière (comme
un bouton back) ou à l'écran d'accueil de votre application (justement pour ne pas être redondant au bouton back) mais vous pouvez l'utiliser comme bon vous
semble. Je vous conseil quand même de l'utiliser à cet usage afin que les utilisateurs Android ne soient pas débousollés lorsqu'ils utilisent votre application.
Pour ce faire, vous devez récupérer la barre d'action grâce à la méthode public ActionBar getActionBar() et apperler la méthode
public abstract void setDisplayHomeAsUpEnabled (boolean showHomeAsUp) dessus en lui donnant la valeur true . Votre icone aura alors une petite
flèche à gauche de l'icone qui vous indiquera que vous pouvez cliquer dessus (voire les captures d'écran ci-dessus).
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Un identifiant lui est automatiquement assigné par le système que vous pourrez tester dans la méthode
public boolean onOptionsItemSelected(MenuItem item) et qui es R.id.home .
Menu contextuel
Vous vous rappelez des anciens menus contextuels ? Malheureusement, c'est une pratique qui peut encore être utilisée dans les applications actuelles mais qui ne
sont pas du tout ergonomiques. Vous êtes obligé de presser un certain temps sur un élément avec votre doigt pour voir apparaitre votre menu. Google a réfléchi à
cette problématique et a trouvé une solution plutôt élégante.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Nous allons profiter de la barre d'action pour a icher un menu intermédiaire qui apparaitra quand bon vous semble (j'entends par là qu'il n'est pas nécessaire de
rester appuyé sur un élément pour faire apparaitre le menu). D'ailleurs, dans notre exemple, nous l'a icherons lorsque l'utilisateur cliquera sur un bouton pour
bien di érencier ce type de menu avec l'ancien mais sachez qu'il est toujours possible de le faire avec l'ancienne méthode. :)
Nous déclarons un nouveau fichier XML destiné à être notre menu intermédiaire. Nous le déclarons comme un menu normal, nous n'avons rien à faire en plus de
ce côté. Tout se jouera dans la partie Java. Vous êtes maintenant censé savoir comment déclarer ce genre de choses, je vous laisse donc ce plaisir. Dans notre
fichier XML d'a ichage, nous déclarons un bouton avec un attribut android:onClick qui prendra la valeur changeContextual .
Si vous ne connaissez pas cet attribut, il vous permet d'assigner une méthode de votre Activity à votre bouton que vous avez spécifié. La méthode
désignée par cet attribut doit être sous la sous la forme public void nomDeLaMethode(View view) . Sinon, votre application plantera.
Nous voulons simplement a icher le menu contextuel, nous allons donc appeler la méthode
public ActionMode startActionMode (ActionMode.Callback callback) sur l'activité. Cette méthode lancera l'a ichage du menu grâce au paramètre
que vous lui donnez en paramètre. Ce paramètre prend une implémentation d'une interface Callback appartenant à ActionMode . Son implémentation exige
4 méthodes à redéfinir :
public boolean onActionItemClicked(ActionMode mode, MenuItem item) pour récupérer l'item sur lequel l'utilisateur a cliqué.
public boolean onCreateActionMode(ActionMode mode, Menu menu) pour désérialiser votre fichier XML contenant votre menu.
public void onDestroyActionMode(ActionMode mode) appelé lorsque votre menu est détruit (lorsqu'il n'est plus a iché à l'écran).
public boolean onPrepareActionMode(ActionMode mode, Menu menu) appelé lorsqu'on tente de rafraichir le menu avec une méthode invalidate.
Pour rester simple, nous allons simplement donner une implémentation aux deux premières méthodes qui fonctionnent exactement comme les menus normaux !
Nous obtenons alors une Activity semble au code ci-dessous et au résultat suivant :
package com.siteduzero.android.actionbar;
import android.app.Activity;
import android.os.Bundle;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
import android.widget.Toast;
import com.siteduzero.android.R;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contextual);
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_trash:
Toast.makeText(getApplicationContext(),
R.string.toast_trash, Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.menu_contextual, menu);
return true;
}
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
@Override
public void onDestroyActionMode(ActionMode mode) {
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
});
}
}
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
A ichage du menu contextuel
Mais alors, cela voudrait dire que nous pouvons créer plusieurs menus contextuels pour une seule classe ?
Vous avez tout compris. Vous pourriez créer plusieurs menus contextuels en fonction de la situation. C'est l'une des forces de ce type de menu et une excellente
alternative à l'ancienne manière de faire !
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Le swipe est une gesture. C'est l'action de passer votre doigt de gauche à droite et inversement sur l'écran de votre terminal.
Si vous ne savez plus comment confectionner des fragments, je vous renvoie au premier chapitre de la partie 1 où les fragments sont abordés de manière
détaillés.
Vous savez comment confectionner des fragments et jusqu'à présent, il vous a fallu les déclarer soit dans un fichier XML d'a ichage que vous désérialisez dans
une classe Fragment soit créer des instances de vos fragments que vous a ichez dynamiquement via l'API destiné à la gestion des fragments. Mais qu'arriverait-
il si vous deviez à chaque fois passez un Bundle à la création d'un Fragment . Vous devriez répéter constamment la manipulation partout dans votre code. Est-
ce qu'il n'y aurait pas moyen d'encapsuler cette pratique quelque part pour une meilleur maintenance de votre code et pouvoir le modifier de manière plus
e icace (sinon, vous devriez changer à chaque endroit où vous créez vos instances. Tant que cela reste un petit projet, ça va mais cela pourrait vite grimper).
Qu'allons-nous faire ? Nous allons rajouter une méthode static dans notre Fragment . Cette dernière nous permettra de créer une instance de notre fragment
et d'encapsuler toutes les informations que nous aurons besoin dans notre fragment. Cette méthode sera donc sous la forme du code ci-dessous pour un
Fragment portant le nom DummyFragment .
public static DummyFragment newInstance(/* informations que je veux donner à mon fragment */) {
// renvoie une instance de mon fragment
}
Je vous rappelle que static signifie que la méthode n'est pas directement attachée aux instances que vous créez de la classe dans laquelle la méthode
est retenue. Par exemple, vous pouvez donc y créer des instances de la classe dans laquelle vous êtes.
Maintenant, imaginons que nous voulons donner une chaîne de caractères à notre Fragment pour l'a icher dans un TextView qu'il contient. L'idée est de
créer un Bundle qui va contenir une chaîne de caractères avec une clé que nous définirons pour le récupérer par la suite dans la création de l'interface du
fragment ; c'est-à-dire dans sa méthode
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) .
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Dans un premier temps, nous allons remplir notre méthode static pour attacher un Bundle à notre fragment. Cela se fait très simplement avec la méthode
public void setArguments(Bundle args) :
C'est aussi simple que cela. Nous créer une instance de notre Fragment , on crée un bundle dans lequel nous placons notre chaîne de caractères, nous
l'attachons à notre Fragment et nous le renvoyons. Pour récupérer ce Bundle , c'est tout aussi simple. Le setter des arguments de notre fragment possède
également un getter. Nous pouvons donc très simplement récupérer le Bundle grâce à la méthode public final Bundle getArguments() . Ainsi, notre
méthode public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) ressemblera à :
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
TextView textView = new TextView(getActivity());
textView.setGravity(Gravity.CENTER);
Bundle args = getArguments();
textView.setText(args.getString("KEY_STRING"));
return textView;
}
Vous l'avez sans doute remarqué mais je n'ai pas utilisé de fichier XML d'a ichage pour mon Fragment . L'XML est une pratique que j'encourage mais dans
le cadre de cet exemple, pour rester simple, j'ai préféré créer dynamiquement un TextView pour a icher notre chaîne de caractères.
C'est tout ! Grâce à cette méthode, vous créez vos fragments grâce à la méthode static et à l'a ichage de ce dernier, vous verrez la chaîne de caractères (ou
n'importe quelle information que vous lui avez donné) à l'écran.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Utilisation du widget ViewPager
L'adaptateur du ViewPager
Bien, nous allons pouvoir commencer les choses sérieuses ! ViewPager est en fait un conteneur comme ListView , GridView , etc. sauf qu'il ne s'utilise pas
avec le même type d'adaptateur. Le ViewPager est conçu pour fonctionner seulement avec des Fragment et rien d'autres. Ainsi, son adaptateur ne possède
pas une méthode View getView(...) qui renvoie une View avec votre conteneur. C'est beaucoup plus simple que cela !
Notre adaptateur devra étendre FragmentPagerAdapter . Cette classe nous imposera d'implémenter 1 constructeur et 2 méthodes :
public ViewPagerAdapter(FragmentManager fm) est le constructeur imposé puisque votre adaptateur devra renvoyer à la super classe une instance
d'un FragmentManager .
public Fragment getItem(int pos) pour récupérer une instance du fragment en cours.
public int getCount() pour connaître le nombre de fragments que devra contenir notre ViewPager .
Si vous avez bien compris le sous-chapitre précédent, vous aurez compris que nous appellerons les méthodes static de nos fragments dans la méthode
public Fragment getItem(int pos) . C'est lui qui est chargé de renvoyer les instances des fragments contenus dans notre conteneur. Je vais maintenant
vous laissez réfléchir à la réalisation de notre adaptateur. Je veux que :
Vous utilisez le fragment que nous avons utilisé dans le sous-chapitre précédent;
Correction
package com.siteduzero.android.viewpager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import com.siteduzero.android.R;
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
public class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int pos) {
switch(pos) {
case 1: return DummyFragment.newInstance("Je suis le premier écran !");
case 2: return DummyFragment.newInstance("Je suis le second écran !");
case 3: return DummyFragment.newInstance("Je suis le troisième écran !");
}
return null;
}
@Override
public int getCount() {
return 3;
}
}
Activité du ViewPager
Nous avons notre Fragment , notre adaptateur, il nous manque plus que notre activité. Pour une fois, notre fichier XML d'a ichage aura une petite particularité.
Nous allons déclarer simplement un ViewPager à sa racine mais pour des soucis de compatibilité, notre conteneur est également redéfini dans le projet v4 que
nous utilisons depuis le début de ce tutoriel. Pour ce faire, le nom de l'élement sera accessible par le chemin android.support.v4.view et nous donnera donc
la déclaration suivante :
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Du côté de notre Activity , c'est exactement pareil qu'avec les autres conteneurs. A la di érence que nous n'étendrons pas Activity mais
FragmentActivity . Cela nous donnera donc le code et le résultat suivant :
package com.siteduzero.android.viewpager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import com.siteduzero.android.R;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_viewpager);
// Set up the adapter.
mSectionsPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
A ichage du premier écran de notre ViewPager
Nous allons indiquer à notre barre d'action qu'il navigera via des « Tabs ».
Navigation en tab
Pour indique que nous comptons utiliser les tabs de la barre d'action, nous devons récupérer notre barre d'action et appeler dessus la méthode
public abstract void setNavigationMode(int mode) . Cette méthode prend en paramètre un mode qui se retrouve comme constante dans la classe
ActionBar :
NAVIGATION_MODE_STANDARD : Valeur par défaut de votre barre d'action. Consiste à a icher votre logo ou icone et le texte avec un sous titre optionnel dans
la barre d'action.
NAVIGATION_MODE_LIST : Change le titre présent dans la barre d'action en une liste déroulante que vous pouvez dérouler lorsque vous cliquez dessus.
NAVIGATION_MODE_TABS : Vous permettra d'utiliser des tabs dans votre barre d'action.
Ainsi, dans notre méthode public void onCreate(Bundle savedInstanceState) de notre Activity , nous faisons la manipulation suivante :
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set up others things
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
Modifier l'indicateur
Pour modifier l'indicateur en fonction de la page courante de l'utilisateur sur le ViewPager , nous allons devoir attacher un listener à notre conteneur via la
méthode public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) . Le lisener OnPageChangeListener impose
d'implémenter 3 méthodes :
public abstract void onPageScrollStateChanged(int state) : Appelé lorsque l'état du défilement change.
public abstract void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) : Appelé lorsque la page courante
est en train d'être modifié.
public abstract void onPageSelected(int position) : Appelé lorsqu'une nouvelle page est sélectionnée.
La dernière méthode est celle qui nous intéresse puisqu'elle nous indique la position dans laquelle nous nous trouvons dans le conteneur. Ainsi, nous pouvons
appeler la méthode public abstract void setSelectedNavigationItem(int position) sur la barre d'action et obtenir le résultat suivant :
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_viewpager);
// Set up others things
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
});
Vous remarquez sans doute que je n'implémente pas les 3 méthodes. C'est simplement grâce à ViewPager.SimpleOnPageChangeListener qui est un
listener alternatif qui me permet de redéfinir uniquement les méthodes que je veux redéfinir. C'est bien pratique mais il est nécessaire d'avoir une petite
idée des méthodes accessibles.
Modifier la page
Pour finir, nous voulons faire l'inverse, nous voulons modifier la page courante du conteneur lorsque nous cliquons sur l'un des tabs de notre activité. Pour ce
faire, nous devons faire plusieurs choses : A la déclaration de nos tabs, nous allons attacher à chaque tab le même listener qui va s'occuper de changer la page
courante de notre ViewPager . Pour ce faire, nous allons implémenter au niveau de l'activité, la classe ActionBar.TabListener . Elle nous oblige alors à
implémenter 3 méthodes :
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) : Appelé lorsqu'un tab n'est plus sélectionné.
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) : Appelé lorsqu'un tab est sélectionné.
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) : Appelé lorsqu'un tab est resélectionné.
@Override
public void onTabSelected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
mViewPager.setCurrentItem(tab.getPosition());
}
Nous pouvons maintenant créer nos tabs grâce à trois méthodes que nous appellerons sur une instance de notre barre d'action :
public abstract void addTab(ActionBar.Tab tab) : Méthode pour ajouter un tab à l'activité.
public abstract ActionBar.Tab setTabListener (ActionBar.TabListener listener) : Méthode pour attacher un listener à notre tab.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Nous utiliserons donc ces méthodes de la manière suivante :
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_viewpager);
// Set up other things
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
actionBar.addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this));
}
}
Vous avez sans doute remarqué la méthode public CharSequence getPageTitle(int position) appelé sur notre adaptateur. Cette méthode est en
fait une méthode optionnel à implémenter qui nous permettra de contenir l' « intelligence » pour le choix du titre de nos pages. Vous n'êtes pas obligé de
recourir à cette méthode, c'est juste un plus que je vous o re.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
A ichage du ViewPager avec une barre d'indicateur en portrait
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
A ichage du ViewPager avec une barre d'indicateur en paysage
Notifier l'utilisateur
Les notifications, cela ne devrait pas être un nouveau concept. Vous en avez déjà développé et cela vous à certainement bien servi dans vos applications.
Cependant, la construction des notifications a changé depuis Android 3 et de nouvelles notifications sont apparus avec Android 4.1. Ce chapitre est donc
destiné uniquement à vous enseignez comment construire ces nouvelles notifications sans parler de services et autres endroits où vous êtes censé lancer
vos notifications. Ces choses ont été abordées dans le tutoriel de Apollidore.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Basique
La création de notifications se fait maintenant par l'intermédiaire d'un service système, chose que vous devriez bien connaître puisqu'une grande partie des
services du système sont gérés de cette manière. Il vous faudra donc en récupérer une instance grâce à l'instruction suivante :
Maintenant que vous savez cela, nous pouvons commencer l'apprentissage de notre première notification basique. Ce type de notification est la seule pouvant
être lancée sur les terminaux Android 3 et plus. Après cela, tous les autres types plus complexes seront apparus avec la version 4.1 d'Android. Cependant, grâce au
projet de compatibilité v4 que nous utilisons constamment dans ce tutoriel, ce procédé est accessible aux versions plus anciennes que la version 3. Par contre, les
nouveaux concepts de la version 4.1 seront ignorés si vous construisez ces types de notifications ; c'est-à-dire que vous pouvez construire des notifications
complexes qui s'a icheront correctement sur la version 4.1 et supérieur mais qui paraitront comme de simples notifications sur les autres versions. C'est un bon
compromis pour rester compatible avec les anciennes versions mais il faut garder cet aspect à l'esprit.
Dans un premier temps, nous aurons besoin d'un Builder spécifique aux notifications. Il est accessible par la classe Notification et s'initialise avec son
constructeur en lui passant un contexte en paramètre :
A partir de cette instance, nous allons construire et récupérer une instance de la classe Notification . Pour la construire, nous avons accès à une petite série de
méthodes :
public NotificationCompat.Builder setWhen(long when) : Donne un timestamp pour l'a ichage de votre notification.
Ce n'est pas toutes les méthodes possibles disponibles à partir d'Android 3, elles sont trop nombreuses et ce tutoriel n'est pas destiné à devenir une
documentation. Si vous voulez en savoir plus, je vous renvoie sur la documentation Android.
Après quoi, nous initialiserons les flags comme vous le faisiez avec les précédentes notifications et nous la lançons grâce à la méthode
public void notify(int id, Notification notification) sur notre service système. Ce dernier prenant en paramètre l'identifiant de la notification et
l'object comportant votre notification.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Nous obtenons donc le code source et le résultat suivant :
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Exécution de la notification basique
Grand texte
Abordons les nouvelles notifications avec un grand texte. Il faut savoir que vous êtes limité en caractères si vous utilisez la méthode
public NotificationCompat.Builder setContentText(CharSequence text) . Elle s'a ichera toujours sur une seule ligne uniquement. Ce n'est donc pas
du tout optimisé si, pour une raison X ou Y, vous désirez écrire plus. Cette nouvelle notification règle le problème très facilement et par l'intermédiaire d'une
nouvelle classe, NotificationCompat.BigTextStyle , que vous devrez initialiser en passant un NotificationCompat.Builder en paramètre.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Vous construisez donc votre builder de la même manière que la notification basique, en omettant la méthode
public NotificationCompat.Builder setContentText(CharSequence text) naturellement, et vous récupérez un objet
NotificationCompat.BigTextStyle en lui passant ce builder en paramètre de son constructeur.
public NotificationCompat.BigTextStyle bigText(CharSequence cs) : A icher un grand texte pour votre notification.
public NotificationCompat.BigTextStyle setBigContentTitle(CharSequence title) : A icher un grand titre pour votre notification.
public NotificationCompat.BigTextStyle setSummaryText(CharSequence cs) : A icher un petit texte à la fin de votre notification destiné à la
résumé.
Sachez que dans les 3 styles, les deux dernières méthodes seront toujours disponibles.
Une fois terminé, vous appelez la méthode public Notification build () qui vous construira la notification que vous pourrez lancer. Ainsi, nous obtenons
le code source et le résultat suivant en utilisant simplement la première des 3 méthodes disponibles pour NotificationCompat.BigTextStyle :
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Exécution de la notification a ichant un grand texte
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Remarquez que j'ai utilisé le même indice pour cette notification et celle de la sous-partie précédente. Cela permettra à Android de récupérer une
notification (si elle est construite) plutôt que d'en créer une nouvelle. C'est une bonne pratique lorsque vous concevez des applications Android. Tentez de
la respecter le plus possible.
Grande image
La grande image est très similaire à la notification avec un grand texte, c'est pourquoi je vais vous laisser réfléchir à la façon de faire pour lancer ce type de
notifications. Sachez simplement que vous allez devoir utiliser la classe NotificationCompat.BigPictureStyle . Vous devriez avoir un résultat similaire au mien (sachant
que je vous demande pas de trouver l'image exacte que j'utilise ^^ ).
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Exécution de la notification a ichant une grande image
Correction
Sans surprise, je pense que vous êtes arrivé aisément au même résultat que moi :
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
NotificationCompat.InboxStyle . Nous aurons donc le résultat suivant :
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Exécution de la notification a ichant une liste
Correction
Imaginez que vous recevez un e-mail. Vous pourriez donner la possibilité à l'utilisateur de le lire ou de l'archiver directement. Avec les anciennes notifications,
cela n'aurait pas été possible. Dorénavant, il existe la méthode
public NotificationCompat.Builder addAction(int icon, CharSequence title, PendingIntent intent) que vous appelez sur votre
NotificationCompat.Builder . Les paramètres correspondent :
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
title est le texte qui s'a ichera à droite de votre bouton.
intent est l'intent qui sera lancé lorsque vous cliquerez sur le bouton, c'est bien entendu un PendingIntent .
Vous êtes censé savoir comment créer des PendingIntent , je passerai donc par l'intermédiaire d'une méthode
private PendingIntent getPendingIntent() qui s'occupera de lancer un intent sur l'activité courante dans laquelle je me trouve. Cependant, vous
pourrez retrouver son implémentation sur le projet GitHub du tutoriel.
Si nous devons compléter le builder du style de la grande image de notre exemple précedent, nous aurons quelque chose semblable à ceci en rajoutant deux
boutons d'action :
builder.setContentTitle(getResources().getText(R.string.big_pic_title))
.setSmallIcon(R.drawable.ic_launcher)
.addAction(android.R.drawable.ic_menu_camera,
getResources().getText(R.string.notification_action_2),
getPendingIntent())
.addAction(android.R.drawable.ic_menu_send,
getResources().getText(R.string.notification_action_1),
getPendingIntent()).setWhen(System.currentTimeMillis());
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Exécution de la notification a ichant une grande image et deux boutons
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Malgré ce qu'un grand nombre d'utilisateurs penseraient, la technologie NFC (Nier Field Communication, ou en français Communication en Champ Proche)
n'est pas neuve. Depuis quelques années seulement, on en entend parler de plus en plus. Notamment grâce aux smartphones qui démocratisent à grande
vitesse cette technologie. Elle vous permettra d'échanger des données à une fréquence faible et à courte distance (moins de 10cm).
Nous n'allons pas rentrer dans les détails techniques de cette technologie dans ce chapitre. Android a prévu une API pour nous permettre de rester, plus ou
moins, à un haut niveau d'abstraction. Cependant, il vous faudra peut-être relire à deux fois certaines explications puisque nous allons devoir directement
jouer avec des bits sur certains points.
ACTION_NDEF_DISCOVERED est le plus grand niveau de propriété dans tout le système. Le système d'identification des tags tentera de lancer une activité
avec cet intent plutôt que d'autres intents en attente dans votre système. Si le système ne trouve aucune activité qui gère cet intent, il passera au type
suivant.
ACTION_TECH_DISCOVERED est un niveau de propriété juste en dessous du précédent. Il sera lancé si le message du tag n'est pas formatté par le standard
NDEF.
ACTION_TAG_DISCOVERED est l'intent qui sera lancé si aucune autre activité n'a été trouvé dans le système pour gérer le tag découvert.
Les messages NDEF sont la tentative de standardisations des forums NFC qui est un consortium international créé pour promouvoir la technologie NFC. Le
problème c'est que cette standardisation n'est pas suivie par tout le monde. Chose pour laquelle Android possède 3 types di érents de tag NFC pour
couvrir un large nombre de tag.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Système d'identification du tag
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Qu'avons-nous là ? Tout simplement un message qui comporte un tableau de record, d'enregistrement, avec un header (comportant des informations comme son
identifiant et autres et un payload qui est la donnée en elle-même). Chaque record possède un espace mémoire assez réduit. Il faut donc penser à les répartir sur
plusieurs records si nous implémentons une application qui écrit des NDEF messages sur des tags ou à bien récupérer chaque record si nous implémentons un
lecteur. Chose que nous allons faire dans la suite de ce chapitre.
La version minimum du SDK que doit spécifier votre application pour accéder à l'entièreté de l'API NFC.
La permission du NFC pour signaler à l'utilisateur que nous utiliserons cette fonctionnalité et pour permettre au Play Store de filtrer les terminaux
compatibles.
<uses-sdk android:minSdkVersion="10"/>
<uses-feature
android:name="android.hardware.nfc"
android:required="boolean" />
Maintenant, pour les activités qui seront destinées à gérer le NFC, nous devrons ajouter un noeud <intent-filter> avec un élément <action> qui indiquera
le type de tag que nous traitons et la catégorie du filtre avec un élément <category> . Nous aurons donc quelque chose comme ceci :
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
Avec ce filtre, le système sera que nous traitons les tags NDEF et pourra proposer notre activité lorsqu'il captera un tag de ce type.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Lecture d'un tag
Activité destiné à gérer la lecture du tag
Bien, on va enfin commencer à s'amuser ! Cependant, nous allons nous limiter aux messages NDEF pour tenter de supporter cette standardisation que Google et
d'autres acteurs comme SONY ou Philips tentent de répandre. De plus, il est bien plus simple d'utiliser les messages NDEF pour apprendre puisque Android o re
une API spécialement prévue pour ce type de messages.
Pour ce faire, nous n'aurons pas besoin de grand chose. Dans une activité quelconque, nous lui attacherons un fichier XML d'a ichage pour a icher simplement
un texte qui sera modifier par le texte que nous enverrons par un tag (ou par une méthode expliquée plus loin pour simuler un tag). Quant à notre activité, nous
nous contenterons de désérialiser ce fichier XML et de jouer avec l'adaptateur NFC, NfcAdapter . Son initialisation se fait avec la méthode
public static NfcAdapter getDefaultAdapter(Context context) qui est une méthode statique pouvant être appelé à partir de la classe précédemment
citée.
Dès que c'est chose faite, nous devons vérifier que l'appareil qui tente de lancer l'activité a bien le NFC ou s'il est bien activé. Pensez qu'il est toujours possible
pour un utilisateur de télécharger une application qui ne lui est pas destinée initialement. Il pourrait donc installer une application qui ne figure pas sur son Play
Store parce que ses appareils enregistrés ne sont pas compatibles. Nous vérifierons que notre adaptateur est bien di érent de null ou s'il est bien activé par la
méthode public boolean isEnabled() .
Notre méthode public void onCreate(Bundle savedInstanceState) ressemblera donc à quelque chose comme le code ci-dessous.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nfc);
this.mTextView = (TextView) findViewById(R.id.textView1);
this.mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Maintenant, pour que notre activité puisse gérer la découverte d'un TAG au premier plan, il est nécessaire de redéfinir la méthode
protected void onResume() et la méthode protected void onPause() . Dans la première méthode, nous activerons la possibilité d'identifier le tag passé
dans un Intent via la méthode
public void enableForegroundDispatch(Activity activity, PendingIntent intent, IntentFilter[] filters, String[][] techLists) . A quoi
correspondent tous ces paramètres ?
Le paramètre Activity est bien entendu destiné à renseigner l'activité sur lequel vous vous trouvez.
Le paramètre PendingIntent renseigne un intent à exécuter plus tard pour indiquer l'activité qui se charge du traitement du tag.
Le paramètre IntentFilter[] pour a iner le traitement des messages, mettre null si vous acceptez tout.
Le paramètre String[][] est renseigné pour exécuter un matching de traitement avec le type de tag de priorité inférieur, mettre null si vous ne voulez
rien matcher.
Quant à la seconde méthode, nous devons désactiver cette possibilité de traitement des tags sur l'activité au premier plan par la méthode
public void disableForegroundDispatch(Activity activity) en renseignant simplement l'activité courante. Vous aurez donc une implémentation
similaire au code suivant :
@Override
protected void onResume() {
super.onResume();
Intent intent = new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
IntentFilter[] filters = null;
String[][] techListArray = null;
mNfcAdapter.enableForegroundDispatch(this, pIntent, filters, techListArray);
}
@Override
protected void onPause() {
super.onPause();
mNfcAdapter.disableForegroundDispatch(this);
}
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Pour finir, nous allons voir comment traiter notre intent qui comporte notre NDEF message. Nous allons donc créer une méthode avec la signature
private void resolveIntent(Intent intent) qui récupérera un tableau de Parcelable correspondant aux données extensions placés par le tag, et ce via la
méthode public Parcelable[] getParcelableArrayExtra(String name) en lui passant en paramètre la constante NfcAdapter.EXTRA_NDEF_MESSAGES .
A partir de là, nous pourrons recopier son contenu dans un tableau du type NdefMessage et traiter les données comme bon nous semble.
Si nous prenons un exemple simple où il existe simplement des données dans le premier enregistrement du message NDEF, on aura une méthode similaire à :
Il vous su it alors d'appeler cette méthode à la fin de la méthode public void onCreate(Bundle savedInstanceState) de votre activité pour gérer l'intent
que vous recevrez dans votre activité lorsque votre système captera un tag NDEF. Votre application est maintenant capable d'intercepter les messages NDEF
découvert par votre système et proposera donc votre activité pour les lire.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
public static NdefMessage createMessage(String text, boolean encode) {
NdefRecord[] records = new NdefRecord[1];
records[0] = createRecord(text, Locale.FRENCH, encode);
return new NdefMessage(records);
}
Pour des soucis de facilité, j'ai placé ces méthodes en static dans une classe utilitaire NFCUtils .
Dans notre activité, nous utiliserons la méthode public static NdefMessage createMessage(String text, boolean encode) que nous appellerons
lorsqu'un utilisera cliquera sur un bouton pour lancer un intent test comportant un message que nous avons défini de la manière suivante :
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
messages[0] = NFCUtils.createMessage("Simule message NDEF", true);
i.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, messages);
startActivity(i);
}
Ainsi, lorsque nous cliquerons sur le bouton, notre système nous proposera notre première activité qui o re la possibilité de gérer des NDEF messages.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Exécution de l'émulateur de messages NDEF
Commençons par implémenter une interface dans notre activité, CreateNdefMessageCallback . Comme vous pouvez le deviner, cette interface servira à
implémenter les méthodes pour créer les messages NDEF lorsque nous envoyons des données à un autre terminal.Nous implémentons donc la méthode
public NdefMessage createNdefMessage(NfcEvent event) de façon très similaire à notre émulateur, à quelques exceptions près. Nous aurons besoin de la
méthode suivante pour créer un mime :
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
mimeBytes, new byte[0], payload);
return mimeRecord;
}
Le mime nous permettra d'indiquer le chemin vers le paquetage contenant l'activité qui permettra de traiter le transfert Beam. Nous devrons donc initialiser un
tableau de record qui comporte l'enregistrement mime et le payload représentant la donnée à transférer. Empaqueter le tout dans un NdefMessage pour
ensuite le retourner dans la méthode. Nous obtenons donc simplement le code suivant :
@Override
public NdefMessage createNdefMessage(NfcEvent event) {
String text = "Message share by Beam !";
NdefRecord[] records = new NdefRecord[] { NFCUtils.createMimeRecord(
"application/com.siteduzero.android.nfc", text.getBytes()) };
NdefMessage msg = new NdefMessage(records);
return msg;
}
Maintenant, pour rendre actif l'appel à cette méthode, nous allons appeler, dans la méthode protected void onCreate(Bundle savedInstanceState) , la
méthode
public void setNdefPushMessageCallback (NfcAdapter.CreateNdefMessageCallback callback, Activity activity, Activity... activities)
sur l'adaptateur NFC que nous avons initialisé juste avant. Nous lui donnons donc l'instance du callback en paramètre et l'activité courante dans laquelle il se
trouve pour rendre opérationnel notre code.
La réception des messages se fait exactement de la même façon que précédent sauf qu'il vous faudra redéfinir une méthode supplémentaire
public void onNewIntent(Intent intent) pour appeler la méthode private void resolveIntent(Intent intent) développée dans la sous partie
précédente de ce chapitre. A partir de là, si vous exécutez votre code et que vous mettez dos à dos deux terminaux avec la technologie Beam, vous arrivez au
resultat suivant :
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Exécution du programme Android Beam
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Bien entendu, ce tutoriel est très loin d'être terminé. Vous pourrez retrouver ce même tutoriel en bêta via ce lien. N'hésitez pas à me donner votre avis pour
faire évoluer ce tutoriel. Il a pour but d'être le plus communautaire possible. Je suis donc ouvert à toutes vos critiques, questions et remarques
constructives !
Remerciements
Aux lecteurs et bêta-testeurs qui me font des critiques constructives sur le contenu de mon tutoriel.
Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD