I. Présentation▲
Sous Android, le composant pour afficher une liste d'images est la Gallery. On y retrouve le même fonctionnement qu'une Listview classiquePersonnaliser une ListView : un Adapter est utilisé pour créer chacun des items de la liste. L'autre partie de ce tutoriel va vous montrer comment télécharger des ressources depuis Internet et s'en servir.
Le but étant d'arriver à un résultat proche de celui-ci :
II. Création du Layout▲
Notre écran se veut très simple afin de cibler les deux ou trois points de ce tutoriel. Dans un LinearLayout, on va venir y placer un composant qui affichera l'image en plein écran (ImageView), ainsi qu'un composant qui affichera la liste des images (Gallery).
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
android
:
orientation
=
"vertical"
android
:
layout_height
=
"fill_parent"
android
:
layout_width
=
"fill_parent"
>
<ImageView
android
:
id
=
"@+id/imageview"
android
:
layout_width
=
"fill_parent"
android
:
src
=
"@drawable/no_photo"
android
:
layout_height
=
"wrap_content"
android
:
layout_weight
=
"0.2"
></ImageView>
<Gallery
android
:
id
=
"@+id/gallery"
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"wrap_content"
android
:
background
=
"@color/blanc"
></Gallery>
</LinearLayout>
III. Création de notre Activity▲
Notre activité va donc s'occuper d'initialiser les deux composants. Par défaut, si aucune image n'est trouvée dans la liste, l'image « no_photo » sera affichée. Cette image est placée dans le répertoire drawable de l'application. Le code sera à l'écoute de la sélection d'une image dans la galerie afin d'afficher l'image en grand dans le composant dédié :
// GUI
private
Gallery gallery;
private
ImageView imgView;
//Data
private
ArrayList<
URL>
mListImages;
private
Drawable mNoImage;
/** Called when the activity is first created. */
@Override
public
void
onCreate
(
Bundle savedInstanceState) {
super
.onCreate
(
savedInstanceState);
setContentView
(
R.layout.main);
//Récupération d'une image par défaut à afficher en cas d'erreur ou de liste vide
mNoImage =
this
.getResources
(
).getDrawable
(
R.drawable.no_photo);
//Construction des URL pour les images
mListImages =
buildListImages
(
);
//Récupération du composant affichant l'image en grand
imgView =
(
ImageView)findViewById
(
R.id.imageview);
//On lui met une image par défaut (la première de la liste ou, par défaut, l'image d'erreur)
if
(
mListImages.size
(
) <=
0
) {
imgView.setImageDrawable
(
mNoImage);
}
else
{
setImage
(
imgView, mListImages.get
(
0
));
}
//Récupération du composant affichant la liste des vignettes
gallery =
(
Gallery) findViewById
(
R.id.gallery);
//On lui attribue notre Adapter qui s'occupera de l'alimenter en vignettes
gallery.setAdapter
(
new
AddImgAdp
(
this
));
//Espacement entre les vignettes
gallery.setSpacing
(
10
);
//Lors d'un clic sur une des vignettes, on affiche l'image correspondante en grand
gallery.setOnItemClickListener
(
new
OnItemClickListener
(
) {
public
void
onItemClick
(
AdapterView parent, View v, int
position, long
id) {
setImage
(
imgView, mListImages.get
(
position));
}
}
);
}
Vu que la liste des images est assez longue, j'ai créé une méthode pour initialiser cette liste :
//Adresse où se trouve l'ensemble des images GIF (numérotées de 1 à 21).
private
final
static
String SERVER_IM =
"http://mickael-lt.developpez.com//tutoriels/android/imagesfaq/"
;
/**
* Permet de construire la liste des URL pour les images
*
@return
*/
private
ArrayList<
URL>
buildListImages
(
) {
int
nbTotalImage =
21
;
ArrayList<
URL>
listFic =
new
ArrayList<
URL>(
);
for
(
int
i =
1
; i <=
nbTotalImage; i++
) {
try
{
listFic.add
(
new
URL
(
SERVER_IM +
"/"
+
i +
".gif"
));
}
catch
(
MalformedURLException e) {
Log.e
(
"DVP Gallery"
, "Erreur format URL : "
+
SERVER_IM +
"/"
+
i +
".gif"
);
e.printStackTrace
(
);
}
}
return
listFic;
}
Ensuite, il nous faut créer un Adapter pour gérer l'affichage de notre Gallery. Vous noterez qu'ici les vues sont recyclées afin d'optimiser la mémoire :
/**
* Notre Adapter qui gère la liste des vignettes
*
@author
Mickaël Le Trocquer
*/
public
class
AddImgAdp extends
BaseAdapter {
int
GalItemBg;
private
Context cont;
public
AddImgAdp
(
Context c) {
cont =
c;
TypedArray typArray =
obtainStyledAttributes
(
R.styleable.GalleryTheme);
GalItemBg =
typArray.getResourceId
(
R.styleable.GalleryTheme_android_galleryItemBackground, 0
);
typArray.recycle
(
);
}
public
int
getCount
(
) {
return
mListImages.size
(
);
}
public
Object getItem
(
int
position) {
return
position;
}
public
long
getItemId
(
int
position) {
return
position;
}
public
View getView
(
final
int
position, View convertView, ViewGroup parent) {
ImageView imgView =
null
;
//Récyclage du composant
if
(
convertView ==
null
) {
imgView =
new
ImageView
(
cont);
}
else
{
imgView =
(
ImageView)convertView;
}
//On affecte notre image à la vignette
if
(
mListImages.size
(
) <=
0
) {
imgView.setImageDrawable
(
mNoImage);
}
else
{
setImage
(
imgView, mListImages.get
(
position));
}
//On défini la taille de l'image
imgView.setLayoutParams
(
new
Gallery.LayoutParams
(
150
, 150
));
imgView.setScaleType
(
ImageView.ScaleType.FIT_XY);
//On fixe un arrière-plan plus sympa
imgView.setBackgroundResource
(
GalItemBg);
return
imgView;
}
}
Maintenant voici le moyen de télécharger une image à partir d'une URL et de l'affecter à un composant de type ImageView :
/**
* Méthode permettant de télécharger une image depuis une URL et de l'affecter à un composant de type ImageView
*
@param
aView
*
@param
aURL
*/
public
void
setImage
(
ImageView aView, URL aURL) {
try
{
URLConnection conn =
aURL.openConnection
(
);
conn.connect
(
);
InputStream is =
conn.getInputStream
(
);
// Bufferisation pour le téléchargement
BufferedInputStream bis =
new
BufferedInputStream
(
is, 8192
);
// Création de l'image depuis le flux des données entrant
Bitmap bm =
BitmapFactory.decodeStream
(
bis);
bis.close
(
);
is.close
(
);
// Fixe l'image sur le composant ImageView
aView.setImageBitmap
(
bm);
}
catch
(
IOException e) {
aView.setImageDrawable
(
mNoImage);
Log.e
(
"DVP Gallery"
, "Erreur téléchargement image URL : "
+
aURL.toString
(
));
e.printStackTrace
(
);
}
}
Vu qu'on souhaite télécharger des fichiers depuis Internet, je vous conseille de rajouter l'autorisation dans votre manifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
package
=
"com.dvp.android.gallery"
android
:
versionCode
=
"1"
android
:
versionName
=
"1.0"
>
<application
android
:
icon
=
"@drawable/icon"
android
:
label
=
"@string/app_name"
>
<activity
android
:
name
=
".DVPGallery"
android
:
label
=
"@string/app_name"
>
<intent-filter>
<action
android
:
name
=
"android.intent.action.MAIN"
/>
<category
android
:
name
=
"android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
</application>
<uses-sdk
android
:
minSdkVersion
=
"4"
/>
<uses-permission
android
:
name
=
"android.permission.INTERNET"
></uses-permission>
</manifest>
IV. Conclusion▲
Pour conclure, le composant Gallery se gère comme un composant ListView dans son utilisation basique. D'autres paramètres permettent de personnaliser ce composant (espacement entre les items, zoom à appliquer sur l'item ayant le focus, etc.). Le téléchargement de ressources sur Internet n'est pas vraiment un problème ici. Le seul point bloquant c'est les temps d'attente pour les téléchargements. Les sources de cette application sont téléchargeables ici : DVP_Gallery.zip
Cet article traite d'un cas simple, pour bien finaliser cet exemple, il faudrait introduire la notion de Thread, d'optimisation pour le téléchargement, etc. Vous pouvez trouver un exemple complet ici : MultiThreading sur android-developersMultiThreading sur android-developers
V. Remerciements▲
Je voudrais remercier Benjamin POINSOT pour sa contribution et ses corrections.
VI. Liens▲
Site du développeurhttp://developer.android.com/index.html
FAQ Androidhttp://android.developpez.com/faq/
Installation de l'environnementhttp://ydisanto.developpez.com/tutoriels/android/debuter/
Création d'un carrouselhttp://davy-leggieri.developpez.com/tutoriels/android/creation-carrousel/
MultiThreading sur android-developershttp://android-developers.blogspot.com/2010/07/multithreading-for-performance.html