1. Code
  2. Mobile Development
  3. Android Development

Android SDK: visualización de imágenes con una galería mejorada

Scroll to top

Spanish (Español) translation by Juan Pablo Diaz Cuartas (you can also view the original English article)

Usando Android Intents y Gallery View, puede permitir que el usuario seleccione imágenes de su dispositivo. En este tutorial combinaremos la selección de imágenes del usuario con la Vista de Galería, que mejoraremos un poco para crear una pantalla interactiva con las imágenes elegidas por el usuario. Si ha completado al menos una aplicación de Android, debería poder llevar a cabo los pasos del tutorial.

La aplicación que crearemos en este tutorial mostrará una lista de desplazamiento de imágenes en miniatura, utilizando la vista de la Galería de Android. El usuario podrá importar imágenes para visualizar pulsando prolongadamente los elementos en la Galería, en los que se los llevará a la aplicación de galería de Android predeterminada o al administrador de archivos elegido. Cuando una imagen seleccionada se devuelve a la aplicación, nos será volver a muestrearla antes de pantalla, para que no utiliza recursos de memoria innecesaria. Al pulsar una imagen en miniatura, la aplicación mostrará la imagen seleccionada en un tamaño más grande.

Paso 1: Crear un proyecto Android

Iniciar un nuevo proyecto Android en Eclipse. En clase de actividad principal de la aplicación, agregue las siguientes declaraciones de importación en la parte superior, antes de la apertura de la clase línea de declaración:

1
import android.app.Activity;
2
import android.content.Context;
3
import android.content.Intent;
4
import android.content.res.TypedArray;
5
import android.database.Cursor;
6
import android.graphics.Bitmap;
7
import android.graphics.BitmapFactory;
8
import android.net.Uri;
9
import android.os.Bundle;
10
import android.provider.MediaStore;
11
import android.view.View;
12
import android.view.ViewGroup;
13
import android.widget.AdapterView;
14
import android.widget.AdapterView.OnItemClickListener;
15
import android.widget.AdapterView.OnItemLongClickListener;
16
import android.widget.BaseAdapter;
17
import android.widget.Gallery;
18
import android.widget.ImageView;

Su declaración de la clase debe comenzar algo como esto, pero con tu propio nombre de la actividad:

1
public class PicSelectActivity extends Activity {

Dentro de la declaración de clase, antes que el método "onCreate", que Eclipse debería incluir automáticamente, agregue estas declaraciones de variables de instancia:

1
//variable for selection intent

2
private final int PICKER = 1;
3
//variable to store the currently selected image

4
private int currentPic = 0;
5
//gallery object

6
private Gallery picGallery;
7
//image view for larger display

8
private ImageView picView;

La primera variable, que es una constante, es para identificar el selector de imagen intención imagen solicitadas del usuario se devuelve a la aplicación. Cuando el usuario largo-presiona un elemento miniatura y es sacado de la aplicación para seleccionar una imagen, usaremos la variable "currentPic" de que miniatura están seleccionando una imagen. Las otras dos variables son para elementos de la interfaz de usuario que necesitamos para hacer referencia a la clase a.

En el archivo de manifiesto, la única adición necesita es el siguiente, principal elemento de actividad de su aplicación:

1
android:configChanges="orientation|keyboardHidden"

Esto permitirá que la aplicación para retener imágenes importadas en los cambios de orientación. Ahora vamos a configurar el texto secuencias que queremos usar dentro de la interfaz de usuario. Abra el archivo "res/values/strings.xml". Eclipse debe haber agregado su nombre de la aplicación ya que se puede modificar si lo desea. Incluir los siguientes elementos de cadena adicionales:

1
<string name="picture">Picture</string>
2
<string name="select_intro">Long-press a thumbnail to add an image</string>
3
<string name="show_intro">Press a thumbnail to display at larger size</string>

Estos son todos para uso dentro de la interfaz de usuario. Ahora vuelve a tu clase de actividad de la aplicación.

Paso 2: Diseñar la aplicación

Antes de que implemente la funcionalidad de la aplicación en Java, vamos a completar los elementos de diseño. Abra su "res/layout/main.xml" archivo. Estaremos utilizando una disposición lineal, así que incluyen el siguiente esquema en tu XML principal:

1
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
2
    android:layout_width="fill_parent"
3
    android:layout_height="fill_parent"
4
    android:orientation="vertical" >
5
   
6
</LinearLayout>

Iremos añadiendo más elementos dentro de la disposición lineal. Comenzar con un texto informativo como el primer elemento de la disposición lineal:

1
<TextView android:layout_width="fill_parent"
2
  android:layout_height="wrap_content"
3
	android:padding="5dp"
4
	android:text="@string/select_intro"
5
	android:gravity="center"
6
	android:textStyle="bold" />

Tenga en cuenta que hablamos de una cadena que definimos en el archivo XML de cadenas. A continuación añadir el elemento de Galería el siguiente:

1
<Gallery
2
	android:id="@+id/gallery"
3
	android:layout_width="fill_parent"
4
	android:layout_height="wrap_content" />

Utilizamos un atributo ID que podemos referirnos a la galería de código Java. A continuación añadir otro punto de vista informativo de texto:

1
<TextView android:layout_width="fill_parent"
2
	android:layout_height="wrap_content"
3
	android:gravity="center"
4
	android:padding="5dp"
5
	android:textStyle="italic"
6
	android:text="@string/show_intro" />

Una vez más, utilizamos un recurso de cadena ya definido. Finalmente, el último elemento de nuestro diseño lineal va a ser una vista de imagen para mostrar una imagen de la galería en tamaño más grande:

1
<ImageView 
2
	android:id="@+id/picture"
3
	android:layout_width="fill_parent"
4
	android:layout_height="fill_parent"
5
	android:contentDescription="@string/picture" />

Necesitamos hacer referencia a este punto de vista en Java, así que usamos un atributo ID. También utilizamos un recurso de cadena como la descripción del contenido. Ahora tenemos que definir algunos atributos de estilo para la galería. Crear un nuevo archivo en el directorio "res/values", llamándolo "attrs.xml". Introduzca el siguiente código:

1
<resources>
2
	<declare-styleable name="PicGallery">
3
		<attr name="android:galleryItemBackground" />
4
	</declare-styleable>
5
</resources>

Van a utilizar algunos de los recursos de estilo de la plataforma Android al estilo de nuestros artículos de la galería y se referirán a éstos en el código Java.

Ahora vuelve a la clase de actividad. Dentro del método "onCreate", el código existente debe aparecer como sigue:

1
super.onCreate(savedInstanceState);
2
setContentView(R.layout.main);

Después de estas líneas, agregar lo siguiente, recuperar referencias a dos de los elementos de la interfaz de usuario:

1
//get the large image view

2
picView = (ImageView) findViewById(R.id.picture);
3
        
4
//get the gallery view

5
picGallery = (Gallery) findViewById(R.id.gallery);

Ahora estamos listos para construir la galería y manejar la interacción con el usuario.

Paso 3: Crear un adaptador de Base

Para construir el punto de vista de la galería, que vamos a crear una clase que extiende la clase Base de adaptador. En la clase de actividad, después del método "onCreate", crear un nuevo esquema de la clase interna como sigue:

1
public class PicAdapter extends BaseAdapter {
2
3
}

Dentro de este nos proporcionará unos métodos que son requeridos por el adaptador de la Base y más adelante agregará algunos métodos personalizados para esta aplicación. En primer lugar, dentro de la nueva clase, agregue algunas variables de instancia:

1
//use the default gallery background image

2
int defaultItemBackground;
3
        
4
//gallery context

5
private Context galleryContext;
6
7
//array to store bitmaps to display

8
private Bitmap[] imageBitmaps;
9
10
//placeholder bitmap for empty spaces in gallery

11
Bitmap placeholder;

La primera variable representa el fondo de elemento de galería de Android que nos hemos referido en nuestro "attrs.xml" archivo. El contexto es para referirse a la interfaz de usuario al agregar elementos. La matriz de mapa de bits almacenará los mapas de bits que vamos a mostrar como parte de la galería. Utilizaremos una imagen de marcador de posición para los elementos de la galería para que el usuario aún no ha seleccionado imágenes.

Vamos a ir adelante y crear el método constructor para nuestra nueva clase de PicAdapter, después de las variables de instancia:

1
public PicAdapter(Context c) {
2
3
	//instantiate context

4
	galleryContext = c;
5
6
	//create bitmap array

7
	imageBitmaps  = new Bitmap[10];
8
            
9
	//decode the placeholder image

10
	placeholder = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
11
	
12
	//more processing

13
	
14
}

Añadiremos más código al método constructor siguiente. Aquí nosotros primero instanciar las variables de matriz de contexto y mapa de bits - vamos a mostrar una galería con 10 artículos en él pero se puede modificar esto si te gusta. Para la demostración, estamos utilizando el icono de launcher ofrece como estándar cuando crear un proyecto Android en Eclipse como nuestra imagen de marcador de posición, pero por supuesto puede crear su propio. Si desea utilizar su propia imagen, guardarla en su carpeta drawable y alterar la línea de "decodeResource" en el código anterior para reflejar su nombre.

Ahora podemos asignar la imagen de marcador de posición para cada posición en el array, para que todas las miniaturas de la Galería inicialmente mostrará-aún dentro del método constructor:

1
//set placeholder as all thumbnail images in the gallery initially

2
for(int i=0; i<imageBitmaps.length; i++)
3
	imageBitmaps[i]=placeholder;

Para completar el método constructor, ahora ajustaremos la imagen de fondo del elemento de Galería:

1
//get the styling attributes - use default Andorid system resources

2
TypedArray styleAttrs = galleryContext.obtainStyledAttributes(R.styleable.PicGallery);
3
4
//get the background resource

5
defaultItemBackground = styleAttrs.getResourceId(
6
	R.styleable.PicGallery_android_galleryItemBackground, 0);
7
8
//recycle attributes

9
styleAttrs.recycle();

Aquí nos referimos al contenido de nuestro "attrs.xml" archivo.

Ahora necesitamos proporcionar unos métodos estándar para cualquier clase extiende la clase Base de adaptador. Primeros incluyen el método de "getCount", después del método constructor:

1
//return number of data items i.e. bitmap images

2
public int getCount() {
3
	return imageBitmaps.length;
4
}

Este método devuelve el número de elementos en la vista Galería. Después de este método, agregue el método estándar "getItem":

1
//return item at specified position

2
public Object getItem(int position) {
3
	return position;
4
}

A continuación añadir el método de "getItemId":

1
//return item ID at specified position

2
public long getItemId(int position) {
3
	return position;
4
}

Usted no necesita preocuparse demasiado por el contenido de estos métodos ya que son estándar. Ahora añadimos un método un poco más complejo requerido por la clase:

1
//get view specifies layout and display options for each thumbnail in the gallery

2
public View getView(int position, View convertView, ViewGroup parent) {
3
4
	//create the view

5
	ImageView imageView = new ImageView(galleryContext);
6
	//specify the bitmap at this position in the array

7
	imageView.setImageBitmap(imageBitmaps[position]);
8
	//set layout options

9
	imageView.setLayoutParams(new Gallery.LayoutParams(300, 200));
10
	//scale type within view area

11
	imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
12
	//set default gallery item background

13
	imageView.setBackgroundResource(defaultItemBackground);
14
	//return the view

15
	return imageView;
16
}

En el método "getView", definimos lo que queremos que aparezca dentro de cada elemento de la galería. Nuestra matriz de mapa de bits va a contener las imágenes que queremos mostrar en cada posición, con el índice de la matriz de un mapa de bits correspondiente a su posición dentro de la galería. Así como la creación de la vista, aquí ponemos el mapa de bits aparecen dentro de ella, junto con algunas propiedades de pantalla. También hemos creado el fondo del artículo que nos hemos referido anteriormente. Puede modificar el tamaño de las miniaturas si quieres. Cada imagen en miniatura aparecerá centrada si es más pequeño que el punto de vista - puede optar, por ejemplo, para estirar la imagen para adaptarse a la thumnbail si lo prefiere, alterando el "ScaleType".

Ahora Desplácese hasta la parte superior de la declaración de clase de actividad principal de la aplicación. Añadir una nueva variable de la instancia que representa una instancia de objeto de la clase nueva que acaba de crear:

1
//adapter for gallery view

2
private PicAdapter imgAdapt;

Ahora, en el método "onCreate", después del código que ya agregado, instanciar la variable Base adaptador y establecerla como el adaptador para la Galería:

1
//create a new adapter

2
imgAdapt = new PicAdapter(this);
3
4
//set the gallery adapter

5
picGallery.setAdapter(imgAdapt);

Cuando la aplicación se lanza inicialmente, se verá algo como esto:

Pic Select LaunchPic Select LaunchPic Select Launch

Ahora estamos listos para manejar la interacción con el usuario.

Paso 4: Permiten al usuario elegir imágenes

Para seleccionar imágenes para mostrar en la galería, el usuario va a largo-prensa artículos miniaturas individuales. En su método "onCreate", después del código existente, agregue el siguiente oyente long-press para cada elemento de la vista de la Galería:

1
//set long click listener for each gallery thumbnail item

2
picGallery.setOnItemLongClickListener(new OnItemLongClickListener() {
3
	//handle long clicks

4
	public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {
5
		//take user to choose an image

6
			
7
	}
8
});

Aquí creamos un nuevo "OnItemLongClickListener" con un método de "onItemLongClick" en su interior. Dentro de este método, agregue el código siguiente:

1
//update the currently selected position so that we assign the imported bitmap to correct item

2
currentPic = position;
3
4
//take the user to their chosen image selection app (gallery or file manager)

5
Intent pickIntent = new Intent();
6
pickIntent.setType("image/*");
7
pickIntent.setAction(Intent.ACTION_GET_CONTENT);
8
//we will handle the returned data in onActivityResult

9
startActivityForResult(Intent.createChooser(pickIntent, "Select Picture"), PICKER);
10
11
return true;

Tome un momento para mirar por encima de este código. En primer lugar, registramos el elemento seleccionado para que sepamos que elemento de la galería una nueva imagen es ser elegida para. A continuación, el código dice que la aplicación para tener los usuarios para su aplicación de selección de imagen solicitadas, que puede ser la galería de Android o una aplicación de administrador de archivos. Al especificar "ACTION_GET_CONTENT", estamos instruyendo la aplicación para devolver lo que el usuario selecciona. Desde que empezamos el selector intención utilizando "startActivityForResult", seremos capaces de manejar la imagen devuelta en el método de "onActivityResult" de actividad.

Qué sucede cuando el selector de imagen que intención comienza dependerá de aplicaciones que el usuario haya instalado. En mi dispositivo, puedo elegir entre dos aplicaciones para la selección de la imagen:

Image Chooser App ChoiceImage Chooser App ChoiceImage Chooser App Choice

Cualquier archivo de imagen seleccionar en cualquiera de estas aplicaciones se devolverán a nuestra aplicación.

Paso 5: Mango devuelve imágenes

Cuando el usuario selecciona una imagen desde su aplicación de manager de galería o archivo, los datos se devolverán al método "onActivityResult". Agregue el método a la clase de actividad utilizando el siguiente esquema:

1
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
2
3
}
4
/java]
5
6
Inside the method, add the following:
7
8
[java]
9
if (resultCode == RESULT_OK) {
10
	//check if we are returning from picture selection

11
	if (requestCode == PICKER) {
12
            //import the image

13
            
14
	}
15
}
16
//superclass method

17
super.onActivityResult(requestCode, resultCode, data);

Aquí comprobamos que hemos recibido datos válidos y que los datos ha regresado de la selección de imagen intención. Llamamos al método de la superclase en el final del cuerpo del método. Dentro de la segunda instrucción "if", vamos a añadir todo el código que tenemos que importar imagen solicitadas del usuario, a partir de la URI de la imagen:

1
//the returned picture URI

2
Uri pickedUri = data.getData();

Tenemos que trabajar un poco más para importar la imagen. Comience por declarar algunas variables auxiliares:

1
//declare the bitmap

2
Bitmap pic = null;
3
4
//declare the path string

5
String imgPath = "";

¡Ahora intento recuperar la ruta de la imagen:

1
//retrieve the string using media data

2
String[] medData = { MediaStore.Images.Media.DATA };
3
//query the data

4
Cursor picCursor = managedQuery(pickedUri, medData, null, null, null);
5
if(picCursor!=null)
6
{
7
	//get the path string

8
	int index = picCursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
9
	picCursor.moveToFirst();
10
	imgPath = picCursor.getString(index);
11
}
12
else
13
	imgPath = pickedUri.getPath();

Aquí recuperamos la imagen los datos de los medios de comunicación, entonces consulta con un cursor, pasando el identificador URI de la imagen elegida por el usuario. El "if" y "else" declaraciones acomodar al usuario elegir su imagen mediante la aplicación de la galería de Android u otro administrador de archivos. El resultado final de este código es que tenemos la ruta a la imagen solicitada.

Paso 6: Mostrar imágenes muestreadas para reducir al mínimo el uso de la memoria

En lugar de la simple lectura de imagen solicitadas del usuario, tenemos que minimizar la cantidad de memoria de nuestra aplicación utiliza. En muchos casos, las imágenes en el dispositivo será mucho más grandes que lo que nosotros podemos mostrar dentro de la aplicación. Por esta razón, queremos volver a muestrear cada imagen antes de leerla en la aplicación. Dentro de la segunda instrucción "if" en "onActivityResult", agregar lo siguiente:

1
//if we have a new URI attempt to decode the image bitmap

2
if(pickedUri!=null) {
3
4
}

Dentro de esta afirmación vamos a muestrear e importar la imagen. Comenzar por especificar el destino ancho y alto para sus imágenes, que debe ser el tamaño más grande que desea que cada imagen que aparezca:

1
//set the width and height we want to use as maximum display

2
int targetWidth = 600;
3
int targetHeight = 400;

Ahora necesitamos un objeto de mapa de bits de opciones para descifrar la imagen:

1
//create bitmap options to calculate and use sample size

2
BitmapFactory.Options bmpOptions = new BitmapFactory.Options();

En primer lugar queremos saber sobre el tamaño de la imagen:

1
//first decode image dimensions only - not the image bitmap itself

2
bmpOptions.inJustDecodeBounds = true;
3
BitmapFactory.decodeFile(imgPath, bmpOptions);
4
5
//image width and height before sampling

6
int currHeight = bmpOptions.outHeight;
7
int currWidth = bmpOptions.outWidth;

Le decimos a las opciones de mapa de bits para descodificar las dimensiones de la imagen, no el mapa de bits de sí mismo. Vamos a utilizar esta información para calcular un tamaño de muestra para importar la imagen a, comience por inicializar una variable para almacenar:

1
//variable to store new sample size

2
int sampleSize = 1;

Calcular el tamaño de la muestra, si el tamaño de la blanco es más pequeño que el tamaño predeterminado de la imagen:

1
//calculate the sample size if the existing size is larger than target size

2
if (currHeight>targetHeight || currWidth>targetWidth) 
3
{
4
	//use either width or height

5
	if (currWidth>currHeight)
6
		sampleSize = Math.round((float)currHeight/(float)targetHeight);
7
	else 
8
		sampleSize = Math.round((float)currWidth/(float)targetWidth);
9
}

Ahora podemos establecer el tamaño de muestra de mapa de bits:

1
//use the new sample size

2
bmpOptions.inSampleSize = sampleSize;

Ahora tenemos que modificar la configuración de opciones de mapa de bits para descodificar el contenido del archivo sí mismo, en lugar de sólo sus dimensiones:

1
//now decode the bitmap using sample options

2
bmpOptions.inJustDecodeBounds = false;

Finalmente podemos descifrar el mapa de bits utilizando nuestras opciones solicitadas:

1
//get the file as a bitmap

2
pic = BitmapFactory.decodeFile(imgPath, bmpOptions);

La variable "pic" ahora tiene la imagen de mapa de bits que desea utilizar en la aplicación.

Paso 7: Añadir elegido imágenes a la galería

Ahora que ya tenemos la imagen seleccionada del usuario importado, podemos añadir a la matriz de la galería. Tenemos que añadir un método personalizado a nuestra clase Base adaptador para ello. Dentro de la declaración de clase interna "PicAdapter", agregue el método siguiente después del método de "getView":

1
//helper method to add a bitmap to the gallery when the user chooses one

2
public void addPic(Bitmap newPic)
3
{
4
	//set at currently selected index

5
	imageBitmaps[currentPic] = newPic;
6
}

Ahora volver a su método "onActivityResult", después de la línea en que usted descifra el archivo de imagen, guardarlo en la variable "pic", agregar lo siguiente:

1
//pass bitmap to ImageAdapter to add to array

2
imgAdapt.addPic(pic);
3
//redraw the gallery thumbnails to reflect the new addition

4
picGallery.setAdapter(imgAdapt);

Primero llamamos al método nuevo para agregar una nueva imagen a la matriz de la galería, luego fijamos el adaptador nuevo para que la nueva imagen aparecerá inmediatamente en la vista Galería.

Paso 8: Mostrar una imagen en mayor tamaño

Por último, queremos mostrar una imagen en mayor tamaño. Una imagen aparecerá en la vista de imagen más grande cuando es inicialmente importado en la aplicación y cuando el usuario lo selecciona de las miniaturas de la galería. En primer lugar, vamos a manejar mostrando una imagen en mayor tamaño cuando el usuario inicialmente las importaciones. En su método "onActivityResult", después de la línea en la que usted llama "setAdapter", agregar lo siguiente:

1
//display the newly selected image at larger size

2
picView.setImageBitmap(pic);
3
//scale options

4
picView.setScaleType(ImageView.ScaleType.FIT_CENTER);

Tenemos una variable de instancia que representa la vista de imagen más grande, así que simplemente puede fijar junto con opciones de escalado. Ahora vamos a manejar mostrando la imagen cuando el usuario hace clic en una miniatura. En la clase "PicAdapter", añadir otro método personalizado después del método de "addPic":

1
//return bitmap at specified position for larger display

2
public Bitmap getPic(int posn)
3
{
4
	//return bitmap at posn index

5
	return imageBitmaps[posn];
6
}

Este método simplemente devuelve la imagen en la posición especificada. Ahora vaya a su método "onCreate" de actividad. Después el oyente de largo-prensa agregó, incluyen los siguientes, implementando una escucha click para cada elemento en la vista de Galería:

1
//set the click listener for each item in the thumbnail gallery

2
picGallery.setOnItemClickListener(new OnItemClickListener() {
3
	//handle clicks

4
	public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
5
		//set the larger image view to display the chosen bitmap calling method of adapter class

6
		picView.setImageBitmap(imgAdapt.getPic(position));
7
	}
8
});

El método de "onItemClick" activará cualquier momento el usuario hace clic en un elemento de la galería. Llamamos al nuevo método de "getPic" hemos añadido a la clase "PicAdapter" para volver al mapa de bits en la posición haga clic en el parámetro como el mapa de bits de vista de imagen para visualizar en mayor tamaño.

Conclusión

Es nuestra aplicación de galería de imágenes completa. Probarlo en un dispositivo real, importar imágenes por miniaturas de largo-presionando y presionando cada miniatura a su vez para visualizar en mayor tamaño. Cuando el usuario ha seleccionado unas imágenes, la aplicación aparecerá algo como esto:

Gallery with Selected ImagesGallery with Selected ImagesGallery with Selected Images

Por supuesto se puede mejorar la aplicación para satisfacer sus propias necesidades, por ejemplo para proporcionar interacción de imagen adicional. El código fuente es proporcionado para la referencia, por lo que puede asegurarse de que tiene todos los elementos combinados correctamente.