IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Créer une galerie connectée

Cet article va vous permettre de comprendre comment fonctionne le composant 'Gallery', mais également comment réaliser des appels serveur afin de télécharger des images, puis les afficher.

27 commentaires Donner une note à l´article (5)

Article lu   fois.

Les deux auteurs

Profil Pro

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

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 :

Image non disponible

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).

Layout main.xml
Sélectionnez
<?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é :

Initialisation de l'activité
Sélectionnez
    // 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 :

Création de la liste des images
Sélectionnez
    //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 :

Adapter pour l'affichage des vignettes
Sélectionnez
    /**
     * 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 :

Téléchargement d'une image et affectation à une vignette
Sélectionnez
    /**
     * 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 :

manifest.xml
Sélectionnez
<?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

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Copyright © 2010 Mickaël Le Trocquer. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.