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