Mostrando entradas con la etiqueta Imagen. Mostrar todas las entradas
Mostrando entradas con la etiqueta Imagen. Mostrar todas las entradas

martes, 27 de agosto de 2013

Galería de Imágenes usando swipe



Como crear una Galería de Imágenes usando "GridView" y "Swipe"
(How create image gallery using gridview and swipe)

Intentaremos crear una galería de imagen bastante sencilla, con la funcionalidad de:
  • Mostrar la miniaturas en un "GridView".
  • Seleccionar una imagen para verla en tamaño original.
  • una vez seleccionada una imagen podremos hacer "swipe" a la derecha o a la izquierda para continuar viendo las imágenes de la galería en tamaño original.
  • Al volver a la galería de miniaturas, siempre tendremos seleccionada la ultima imagen que vimos en tamaño original.  

Para ello crearemos solamente tres activities.
- MainActivity (Se crea por defecto cuando creamos el proyecto)
- ShowGalleryActivity
- SwipeImageActivity

Y ademas crearemos cuatro layouts.
- activity_main (Se crea por defecto cuando creamos el proyecto)
- images_gallery (Contiene el GridView)
- show_image (Es el contenedor de la imagen original, con algunos textos de ayuda)
- swipe_image_layout (Contiene el componente ViewPager, donde cargaremos el layout show_image, con las imágenes originales para hacer el efecto de "swipe").

Las imágenes que utilizaremos para esta galería las colocaremos, en una de nuestras carpetas de recursos, en nuestro caso drawable-xhdpi

Para este tutorial hemos usado Android Studio (I/O Preview) 0.2.5

1.- Después de haber creado un nuevo projecto, copiaremos nuestras imágenes a la carpeta de recursos drawable-xhdpi.
2.- A continuación creamos un layout llamado images_gallery




3.- Creamos una Activity llamada ShowGalleryActivity y la enlazamos con el 
images_gallery layout (setContentView(R.layout.images_gallery);)

A continuación el código con los comentarios suficientes para que se pueda entender.
public class ShowGalleryActivity extends Activity {

    public static int mSelected = 0;
    private GridView gridview;
    // Hacemos referencia a nuestras imagenes en miniatura de la carpeta de recursos
    public static Integer[] mImagesIds = {
            R.drawable.i1_thumb, R.drawable.i2_thumb,
            R.drawable.i3_thumb, R.drawable.i4_thumb,
            R.drawable.i5_thumb, R.drawable.i6_thumb,
            R.drawable.i7_thumb, R.drawable.i8_thumb,
            R.drawable.i9_thumb, R.drawable.i10_thumb,
            R.drawable.i11_thumb, R.drawable.i12_thumb,
            R.drawable.i13_thumb, R.drawable.i14_thumb,
            R.drawable.i15_thumb, R.drawable.i16_thumb,
            R.drawable.i17_thumb, R.drawable.i18_thumb,
            R.drawable.i10_thumb, R.drawable.i20_thumb,
            R.drawable.i21_thumb, R.drawable.i22_thumb,
            R.drawable.i23_thumb, R.drawable.i24_thumb,
            R.drawable.i25_thumb, R.drawable.i26_thumb,
            R.drawable.i27_thumb, R.drawable.i28_thumb,
            R.drawable.i29_thumb, R.drawable.i30_thumb,
            R.drawable.i31_thumb
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.images_gallery);

        //Hacemos referncia nuestro GridView
        gridview = (GridView) findViewById(R.id.gridview);
        //Asignamos el ImageAdapter que hemos creado en esta misma clase al GridView
        gridview.setAdapter(new ImageAdapter(this));
        //Nos movemos al elemento seleccionado del GridView
        gridview.setSelection(mSelected);
    }
    @Override
    protected void onStart() {
        super.onStart();
        gridview = (GridView) findViewById(R.id.gridview);
        gridview.setAdapter(new ImageAdapter(this));
        gridview.setSelection(mSelected);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.show_gallery_activity, menu);
        return true;
    }

    //ImageAdapter para almacenar las imagemes en el GridView
    public class ImageAdapter extends BaseAdapter {
        private Context mContext;
        public ImageAdapter(Context c) {
            mContext = c;
        }
        public int getCount() {
            return mImagesIds.length;
        }
        public Object getItem(int position) {
            return null;
        }
        public long getItemId(int position) {
            return 0;
        }

        // Creamos un ImageView por cada imagen miniatura referenciada en nuestro ImageAdapter
        public View getView(final int position, View convertView, ViewGroup parent) {
            ImageView imageView;
            if (convertView == null) {  // if it's not recycled, initialize some attributes
                imageView = new ImageView(mContext);
                imageView.setLayoutParams(new GridView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 130));
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
                    imageView.setCropToPadding(true);
                } else {
                    imageView.setScaleType(ImageView.ScaleType.FIT_XY);
                }
                imageView.setPadding(2, 2, 2, 2);
            } else {
                imageView = (ImageView) convertView;
            }
            //Asignamos a cada ImageView una imagen de nuestro "Array" de recursos
            //utilizamos "setImageResource" ya que nuestras imagenes estan almacenadas en una
            //carpeta de recursos en nuestro proyecto.
            // "mImagesIds" es un Array de enteros, ya que almacena el Id del recurso, no la imagen en si.
            imageView.setImageResource(mImagesIds[position]);

            //En el evento click del ImageView obtenemos el indice de la imagen seleccionada
            imageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    mSelected = (Integer) view.getTag();
                    notifyDataSetChanged();

                    String index = String.valueOf(position);
                    Bundle extras = new Bundle();

                    //Pasamos el indice de la imagen seleccionada a la activity que se encarga de mostrar la image Original
                    //y hacer el "swipe"
                    extras.putString("position", index);
                    startActivity(new Intent(ShowGalleryActivity.this, SwipeImageActivity.class).putExtras(extras).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
                }
            });
            try {
                imageView.setTag(position);
                //Ponemos un borde de color naranja a la imagen en miniatura seleccionada en el GrisView
                if (position == mSelected) {
                    imageView.setBackgroundColor(Color.parseColor("#ff6203"));
                } else {
                    imageView.setBackgroundColor(Color.TRANSPARENT);
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return imageView;
        }
    }
}


5.- A continuación creamos un layout llamado swipe_images_layout que servirá de contenedor de la colección de imágenes


    

6.- Creamos otro layout con la estructura de cada elemento de la colección de imágenes.


    

    

        
    

    

        
    


Nota: Aquí usamos el componente <android.support.v4.view.ViewPager> por esta razón, debemos copiar en la carpeta lib de nuestro proyecto la librearía: android-support-v4.jar  

6.- Creamos una activity llamada SwipeImageActivity. A continuación les dejo el código con los comentarios suficientes para que se pueda entender.

public class SwipeImageActivity extends Activity {

    //Hacemos referencia a nuestras imagenes originales de la carpeta de recursos
    public static Integer[] mImagesIds = {
            R.drawable.i1, R.drawable.i2,
            R.drawable.i3, R.drawable.i4,
            R.drawable.i5, R.drawable.i6,
            R.drawable.i7, R.drawable.i8,
            R.drawable.i9, R.drawable.i10,
            R.drawable.i11, R.drawable.i12,
            R.drawable.i13, R.drawable.i14,
            R.drawable.i15, R.drawable.i16,
            R.drawable.i17, R.drawable.i18,
            R.drawable.i10, R.drawable.i20,
            R.drawable.i21, R.drawable.i22,
            R.drawable.i23, R.drawable.i24,
            R.drawable.i25, R.drawable.i26,
            R.drawable.i27, R.drawable.i28,
            R.drawable.i29, R.drawable.i30,
            R.drawable.i31
    };

    private boolean hideSwipeText;
    private String[] imagesDescriptions;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.swipe_images_layout);

        //Optenenos del GridView de la activity anterior el indice de la imagen que hemos
        //seleccionado
        String i = getIntent().getStringExtra("position");
        //Lo convertimos a entero
        int index = Integer.parseInt(i);

        //Obtenemos la decripcion de la imagen seleccionada de una lista en la carpeta values\arrays.xml
        imagesDescriptions = getResources().getStringArray(R.array.images_descriptions);

        SwipeImagePagerAdapter swipeNewsAdapter = new SwipeImagePagerAdapter();
        ViewPager newsPager = (ViewPager) findViewById(R.id.swipe_pager);
        newsPager.setAdapter(swipeNewsAdapter);
        newsPager.setCurrentItem(index);

        newsPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int i, float v, int i2) {
                ShowGalleryActivity.mSelected = i;
            }

            @Override
            public void onPageSelected(int i) {

            }

            @Override
            public void onPageScrollStateChanged(int i) {

            }
        });
    }

    //Creamos el SwipeImagePagerAdapter. Donde utilizaremos el layout "show_images"
    //para cargar la imagen original y los textos de descripcion de la imagen
    private class SwipeImagePagerAdapter extends PagerAdapter {
        @Override
        public int getCount() {
            return ShowGalleryActivity.mImagesIds.length;
        }
        /**
         * Create the page for the given position.  The adapter is responsible
         * for adding the view to the container given here, although it only
         * must ensure this is done by the time it returns from
         * {@link #finishUpdate(android.view.ViewGroup)}.
         *
         * @param collection The containing View in which the page will be shown.
         * @param position   The page position to be instantiated.
         * @return Returns an Object representing the new page.  This does not
         * need to be a View, but can be some other container of the page.
         */
        @Override
        public Object instantiateItem(ViewGroup collection, int position) {

            LayoutInflater inflater = (LayoutInflater) collection.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            //Refereciamos el show_images layout
            View view = inflater.inflate(R.layout.show_images, null);
            LinearLayout swipeDescription = (LinearLayout) view.findViewById(R.id.swipe_description);

            if (hideSwipeText) {
                swipeDescription.setVisibility(View.GONE);
            }

            hideSwipeText = true;

            //Refereciamos el objeto ImageView del "show_images" layout
            ImageView imageView = (ImageView) view.findViewById(R.id.gallery_image);

            //Asignamos a cada ImageView una imagen de nuestro "Array" de recursos
            //utilizamos "setImageResource" ya que nuestras imagenes estan almacenadas en una
            //carpeta de recursos en nuestro proyecto.
            // "mImagesIds" es un Array de enteros, ya que almacena el Id del recurso, no la imagen en si.
            imageView.setImageResource(mImagesIds[position]);

            //Refereciamos el objeto TextView del "show_images" layout, para colocar la descripcion de la imagen
            TextView imageDescription = (TextView) view.findViewById(R.id.image_description);

            //Asignamos el test descriptivo de la imagen al objecto TextView.
            imageDescription.setText(imagesDescriptions[position].toString());

            //Adicionamos el "view" que hemos creado con los objectos ImageView y TextView a la coleccion ViewGroup
            collection.addView(view, 0);

            return view;
        }

        /**
         * Remove a page for the given position.  The adapter is responsible
         * for removing the view from its container, although it only must ensure
         * this is done by the time it returns from {@link #finishUpdate(android.view.ViewGroup)}.
         *
         * @param collection The containing View from which the page will be removed.
         * @param position   The page position to be removed.
         * @param view       The same object that was returned by
         *                   {@link #instantiateItem(android.view.View, int)}.
         */
        @Override
        public void destroyItem(ViewGroup collection, int position, Object view) {
            collection.removeView((View) view);
        }
        /**
         * Determines whether a page View is associated with a specific key object
         * as returned by instantiateItem(ViewGroup, int). This method is required
         * for a PagerAdapter to function properly.
         *
         * @param view   Page View to check for association with object
         * @param object Object to check for association with view
         * @return
         */
        @Override
        public boolean isViewFromObject(View view, Object object) {
            return (view == object);
        }
        /**
         * Called when the a change in the shown pages has been completed.  At this
         * point you must ensure that all of the pages have actually been added or
         * removed from the container as appropriate.
         *
         * @param arg0 The containing View which is displaying this adapter's
         *             page views.
         */
        @Override
        public void finishUpdate(ViewGroup arg0) {
        }

        @Override
        public void restoreState(Parcelable arg0, ClassLoader arg1) {
        }
        @Override
        public Parcelable saveState() {
            return null;
        }
        @Override
        public void startUpdate(ViewGroup arg0) {
        }
    }
}

Nota: Las descripciones de las imagenes se encuentran en la carpeta res\values\arrays.xml

7. -Por ultimo modificaremos nuestro Main Activity para hacer el llamado nuestra galería de imágenes:

El layout associado a la Main Activity (activity_main) queda de la siguiente manera:


    

En la clase MainActivity, capturamos el evento del click del botón, para así mostrar la galería:


public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button showGallery = (Button) findViewById(R.id.button);

        showGallery.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(MainActivity.this, ShowGalleryActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
            }
        });
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        return true;
    } 
}
Así debería quedar nuestro proyecto:

Y el resultado seria el siguiente:

Y después de seleccionar una imagen:

Puede descargar el código fuente en: ImageGallerySource