sábado, 23 de junio de 2012

Crear tu propia Galería de Imágenes

Android ofrece su propia galería de imágenes por defecto. En este post se va a mostrar una alternativa a la imagen inferior. Ésta, como podemos observar, se compone de un visor de las imágenes y debajo la imagen ampliada. Un ejemplo podría ser imagen siguiente:


Si este método no os gusta, podéis usar el que se presenta en este post. Si queréis que mediante un "gesto en pantalla", cómo podría ser arrastrar el dedo por ella, pueda cambiar la imagen añadid el siguiente código a vuestro proyecto. A continuación un completo ejemplo:

Contiene la image que se cambiara en la vista.
res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/vista_fotos"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF"
    android:orientation="vertical" >
    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:scaleType="centerInside" />
</RelativeLayout>

Contiene el código que detecta el movimiento del dedo del usuario. Y posteriormente, ejecuta el cambio de imagen. Esta tiene que implementar un "OnClickListener" porqué así detectamos el contacto del usuario con la vista. En otro caso, no se activaría el "gestureListener".
src/SwypeImagesActivity.java
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.RelativeLayout;

public class SwypeImagesActivity extends Activity implements OnClickListener {

    // Custom settings
    private static final int SWIPE_MIN_DISTANCE = 120;
    private static final int SWIPE_MAX_OFF_PATH = 250;
    private static final int SWIPE_THRESHOLD_VELOCITY = 30;
    private GestureDetector mGestureDetector;
    private View.OnTouchListener mGestureListener;
    private ImageView mImageView;
    private Integer[] mImagesList = { R.drawable.image1, R.drawable.image2,
            R.drawable.image3, R.drawable.image4};
    private int mPhoto;
    private RelativeLayout mView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPhoto = 0;
        setContentView(R.layout.main);
        mView = (RelativeLayout) findViewById(R.id.vista_fotos);
        mImageView = (ImageView) findViewById(R.id.image);

        // initialize with the first image
        mImageView.setImageResource(mImagesList[mPhoto]);

        // Gesture detection
        mGestureDetector = new GestureDetector(new MyGestureDetector());
        mGestureListener = new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                return mGestureDetector.onTouchEvent(event);
            }
        };
        // prevent the view to be touched
        mView.setOnClickListener(this);
        mView.setOnTouchListener(mGestureListener);
    }

    public class MyGestureDetector extends SimpleOnGestureListener {
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                float velocityY) {
            try {
                if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
                    return false;
                if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
                        && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    mPhoto = (mPhoto + 1) % mImagesList.length;
                    mImageView.setImageResource(mImagesList[mPhoto]);
                } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
                        && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    mPhoto = (mPhoto - 1) % mImagesList.length;
                    if (mPhoto < 0) {
                        mPhoto = 0;
                    }
                    mImageView.setImageResource(mImagesList[mPhoto]);
                }
            } catch (Exception e) {
                Log.e("SwypeImagesActivity", "error on gesture detector");
            }
            return false;
        }
    }
    @Override
    public void onClick(View v) {
        // Necessary because the view must have on touch listener
    }
}

It works!

Roger Sala,

15 comentarios:

  1. Excelente tutorial. Me ayudó muchisimo el swype.
    Gracias!

    ResponderEliminar
  2. Me alegro mucha Marisol. Si necesitas algo más no dudes en comentar, por eso estamos.
    Saludos!

    ResponderEliminar
  3. Por si acaso no tiens el codigo de la aplicacion que se muestra la captura=

    ResponderEliminar
  4. Me podran ayudar con esta misma galeria pero que vea las imagenes de una carpeta en la sd especifica?

    ResponderEliminar
  5. Hola Luis,

    Este fin de semana lo miro y te ayudo con el código.

    Saludos!

    ResponderEliminar
  6. Buenas! Roger pudiste encontrar la forma de ver las imágenes desde una carpeta específica de la sd, en vez de tener las imágenes en la misma app?
    Gracias de antemano!

    ResponderEliminar
  7. Hola Luís,

    Puedes usar esta función para coger las imagenes de la SD:

    private Cursor getImagesSD() {
    String[] imgColumnID = { MediaStore.Images.Thumbnails._ID };

    Cursor cursor = managedQuery(
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imgColumnID,
    MediaStore.Images.Media.DATA + " like ? ",
    new String[] { "%yourFolderHere%" }, null);

    return cursor;
    }

    El managedQuery esta deprecated para Activity. Puede user CursorLoader (http://developer.android.com/reference/android/content/CursorLoader.html) si lo prefieres.

    Saludos! Y muchas suerte.

    Roger

    ResponderEliminar
    Respuestas
    1. Muchas gracias, lo probaré a ver que tal :D

      Eliminar
    2. Estoy confundido, como agrego esa parte del codigo a la galeria que hiciste? porque debajo se llama a mImagesList que son los de drawable que estaban antes y que elimino para usar los de la sd, entonces como hago para llamar a los nuevo del cursor

      Eliminar
    3. Luis,

      1.- Tienes que añadir el código que te pase justo después del setContentView.
      2.- Parser el Cursor obteniendo la imagen (te recomiendo que la crees como Bitmap).
      3.- Cambiar el tipo de mImagesList a ArrayList.
      4.- Cambiar el setImageResource por setImageBitmap.

      Espero que te funcione.
      Saludos!

      Eliminar
  8. OK gracias! Probaré a ver que tal! ;) (Y)

    ResponderEliminar
  9. Hola, ante todo muy bueno este ejemplo, lo que quisiera saber es si puedes compartir el proyecto de la galeria de imagines que muestras al comienzo del mismo. A su vez consulto, sera factible añadir un textview para mostrar una descripcion segun la imagen mostrada?

    aguardo tu respuesta. muchas gracias de antemano.

    saludos cordiales,

    ResponderEliminar
  10. Tengo un problema no me visualiza la parte de arriba cual puede ser el problema???

    ResponderEliminar
  11. Amigo, es posible crear una carpeta propia dentro de la aplicación, la cual guarde imágenes y luego poder visualizarlas en la galería que creamos?

    ResponderEliminar
  12. Sí! Sólo tienes que alojarla por ejemplo en /assets o bien puedes crearla dentro de res/drawable/ y recuperarlos de allí. Aquí tienes algún ejemplo.

    http://stackoverflow.com/questions/7645268/how-to-load-a-image-from-assets

    ResponderEliminar