programador

iván albizu

Main Blog

Blog

GridView con librería Picasso II

GridView con Picasso II

Continuando con mi publicación anterior sobre GridView con librería Picasso I, voy a implementar:

  • Usar las imágenes de nuestro móvil
  • Posibilidad de controlar el número de columnas del GridView
  • Permitir ver la imagen con la aplicación por defecto
  • Mejorar la visualización en función del tamaño de pantalla

1. Usar imágenes de nuestro móvil.

Para obtener las imágenes que tenemos en nuestro teléfono usaremos un método estático que nos devuelve un ArrayList de String. El método lo implementamos dentro de MainActivity.java

Su código:

/**
 * Getting All Images Path
 * 
 * @param activity
 * @return ArrayList with images Path
 */
public static ArrayList<String> getAllShownImagesPath(Activity activity) {
	Uri uri;
	Cursor cursor;
	int column_index_data, column_index_folder_name;
	ArrayList<String> listOfAllImages = new ArrayList<String>();
	String absolutePathOfImage = null;
	uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

	String[] projection = { MediaColumns.DATA,
			MediaStore.Images.Media.BUCKET_DISPLAY_NAME };

	cursor = activity.getContentResolver().query(uri, projection, null,
			null, MediaStore.Images.Media.DATE_ADDED);

	column_index_data = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
	column_index_folder_name = cursor
			.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
	while (cursor.moveToNext()) {
		absolutePathOfImage = cursor.getString(column_index_data);

		listOfAllImages.add(absolutePathOfImage);
	}

	Collections.reverse(listOfAllImages);
	return listOfAllImages;
}

Necesitamos ahora modificar el código del adaptador, ya que su constructor recibía como uno de sus parámetros un Array de String. Por tanto

  1. La variable que contiene las imágenes será private ArrayList<String> items;
  2. El contructor será del tipo public GridviewAdapter(Context context, ArrayList<String> items) {…}.
  3. Para determinar cuantos elementos tiene el Array ahora será public int getCount() { return items.length; }
  4. Para conocer sobre que imagen se itera dentro de getView necesitaremos cambiarlo a public Object getItem(int position) { return items.get(position); }
  5. Para hacer uso de la librería Picasso modificaremos el método que obtiene la imagen a procesar .load(“file://”+items.get(position)). Concatenamos antes de la ruta de la imagen un trozo de String para referenciarla correctamente: “file://”

Hasta aquí ya usamos las imágenes de nuestro móvil para crear el GridView.

2. Controlar el número de columnas.

Necesitaremos crear y modificar varios archivos.

  1. Crear el menú de opciones, sobre esto ya hice un vídeo
  2. Registramos el menú en el MainActivity.java con public boolean onCreateOptionsMenu(Menu menu) {…}
  3. Le damos funcionalidad a los ítems del menú con public boolean onOptionsItemSelected(MenuItem item) {…}
    1. Establecemos al comienzo todos los ítems como no seleccionados item.setChecked(false);
    2. Según ítem seleccionado, pasamos (numColumn) a una variable el valor de columnas y establecemos el ítem como “checked” item.setChecked(true);
    3. Después del SWITCH le comunicamos al GridView el número de columnas: .setNumColumns(numColumn); y el adaptador actualizado: .setAdapter(new GridviewAdapter(MainActivity.this, getAllShownImagesPath(this), numColumn));
    4. Añadimos nueva variable al adaptador y modificamos el constructor para que reciba el tercer parámetro que indica el número de columnas: public GridviewAdapter(Context context, ArrayList<String> items, int numColumn) {..}

Código XML del menú:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:app="http://schemas.android.com/apk/res-auto"
	xmlns:tools="http://schemas.android.com/tools"
	tools:context="eu.ivanalbizu.picassogridviewgallery.MainActivity" >

	<group android:id="@+id/group1" android:checkableBehavior="single">
		<item
			android:id="@+id/oneColumn"
			android:orderInCategory="100"
			android:title="@string/one_column"
			app:showAsAction="never"/>
		<item
			android:id="@+id/twoColumn"
			android:orderInCategory="200"
			android:title="@string/two_column"
			app:showAsAction="never"/>
		<item
			android:id="@+id/threeColumn"
			android:orderInCategory="300"
			android:title="@string/three_column"
			app:showAsAction="never" android:checked="true"/>
		<item
			android:id="@+id/fourColumn"
			android:orderInCategory="400"
			android:title="@string/four_column"
			app:showAsAction="never"/>
	</group>

</menu>

Código de creación y control del menú:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
	getMenuInflater().inflate(R.menu.main, menu);
	getOverflowMenu();
	return super.onCreateOptionsMenu(menu);
}

private void getOverflowMenu() {

	try {
		ViewConfiguration config = ViewConfiguration.get(this);
		Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
		if (menuKeyField != null) {
			menuKeyField.setAccessible(true);
			menuKeyField.setBoolean(config, false);
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
	item.setChecked(false);
	
	switch (item.getItemId()) {
	case R.id.oneColumn:
		numColumn=1;
		item.setChecked(true);
		break;
	case R.id.twoColumn:
		numColumn=2;
		item.setChecked(true);
		break;
	case R.id.threeColumn:
		numColumn=3;
		item.setChecked(true);
		break;
	case R.id.fourColumn:
		numColumn=4;
		item.setChecked(true);
		break;
	default:
		break;
	}
	
	gridView.setNumColumns(numColumn);
	gridView.setAdapter(new GridviewAdapter(MainActivity.this,
			getAllShownImagesPath(this),numColumn));
	
	return super.onOptionsItemSelected(item);
}

3. Permitir ver la imagen con la aplicación por defecto.

Dentro del método onCreate(…) incluimos listener al GridView del tipo “ítem seleccionado”.

Su código:

gridView.setOnItemClickListener(new OnItemClickListener() {

	@Override
	public void onItemClick(AdapterView<?> parent, View view,
			int position, long id) {
		String rutaDeLaImagen = gridAdapter.getItem(position).toString();

		Intent intent = new Intent();
		intent.setAction(Intent.ACTION_VIEW);
		intent.setDataAndType(Uri.parse("file://" + rutaDeLaImagen), "image/*");
		startActivity(intent);
	}
});

4. Mejorar la visualización en función del tamaño de pantalla.

Para optimizar el ancho de pantalla del móvil y el número de columnas a mostrar modificaremos el código del getView del adaptador. Se necesita obtener el ancho de pantalla del teléfono (detecta si está vertical u horizontal el móvil).

Al método .resize(…) de la librería Picasso le pasamos como parámetros el resultado de dividir el ancho del móvil entre el número de columnas int imageWidth = (int) (width / numColumn);

El método completo del getView es:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
	WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
	Display display = wm.getDefaultDisplay();
	Point size = new Point();
	display.getSize(size);
	int width = size.x;
	
	int imageWidth = (int) (width / numColumn);
	
	//Declaramos el ImageView
	ImageView img = null;
	if (convertView == null) {
		//Referenciamos el ImageView
		img = new ImageView(context);
		//Referenciamos el ImageView al convertView
		img.setPadding(10,0,10,0);
		convertView = img;
	} else {
		img = (ImageView) convertView;
	}

	//Uso de la librería Picasso
	Picasso.with(context)
		//Cargamos la imagen sobre la que se esté iterando
		.load("file://"+items.get(position))
		//Imagen por defecto usada mientras se cargan las imágenes
		.placeholder(R.drawable.picture)
		.noFade()
		.resize(imageWidth, imageWidth)
		.centerCrop()
		//Se aplica sobre la imagen (ImageView - se hizo referencia a "convertView")
		.into(img);
	
	return convertView;
}

Vídeo del proyecto:

Descargar el código completo de el GridView con librería Picasso

Esta entrada tiene 4 comentarios

  1. Alec dice:

    Hello!
    I was wondering if you could help me a litte. I’m using Picasso library to load images from URL, everything works perfect, the only problem is that I don’t know how to implement a click listener so I will be able to click on any image and zoom it to full screen.
    Thank you!

  2. Iván Albizu dice:

    A quick possibility is to put a listener on the gridview to detect on that image is pressed, and get the URL of the image. (In one of my example I put within Array of String). Sending the URL by in intent to another Activity in which Picasso used again, as you can see in the example.

    Get URL:

    gridView.setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView< ?> parent, View view,
    int position, long id) {
    Intent i = new Intent(getApplicationContext(), ZoomActivity.class);
    i.putExtra(“path”, items[position]);
    startActivity(i);
    }
    });

    Another Activity:

    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_zoom);

    WindowManager wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    Point size = new Point();
    display.getSize(size);
    int width = size.x;
    int imageWidth = (int) (width / 1.2);

    zoom = (ImageView) findViewById(R.id.imageView1);

    String path = getIntent().getExtras().getString(“path”);

    Picasso.with(getApplicationContext())
    .load(path)
    .placeholder(R.drawable.picture)
    .resize(imageWidth, imageWidth)
    .into(zoom);
    }

    I hope you find it useful.

  3. Eironeia dice:

    Hey there!

    I’m going crazy finding some damn code that can allow do the same open a picture when you click on them but not in the phone open it to the aplication via URL.

    I would be very glad if you answer ..!!

  4. Iván Albizu dice:

    Some time ago I published two other post where the images were read from URL

    http://ivanalbizu.eu/gridview-con-libreria-picasso-viewholder/
    http://ivanalbizu.eu/gridview-con-libreria-picasso/

    I hope it helps you

Deja un comentario

Usted debe loguearse para dejar un comentario.