jueves, 13 de febrero de 2014

ListView Android

Hola, ahora explicaremos un poco como utilizar un ListView y los elementos que necesitamos para crear uno propio y personalizado.

Todas las entradas dan por hecho que sabemos crear un proyecto nuevo, un Activity nuevo, y tenemos conceptos de la programación en java.

El manejo de un ListView es algo mas complejo que la utilización de un TableLayout (mostrado en la entrada anterior TableLayout Android tutorial) Tampoco es algo muy dificil, solo es cuestión de "agarrarle el modo" bien, pues vamos al ejemplo práctico.

Un ListView nos permite personalizar al casi al 100% el diseño de cada celda que vamos a mostrar cuando la personalizamos (que es lo que haremos en esta entrada), pues la definiremos en un XML independiente que solo mostrará lo que llevará cada celda de información.

Pues para ilustrar el ejemplo queremos que al final podamos visualizar una lista de n cantidad de elementos, cada fila de nuestra lista, tendra una imagen, un titulo y un subtitulo, se podrá hacer Scroll en la lista, y cada elementos de la lista nos lanzará a un nuevo Activity que nos dirá en que fila fue en donde hicimos click.

1.- Creamos nuestra interfaz gráfica con un simple ListView dentro del layout principal, le asignamos su respectivo ID para su manejo en JAVA en mi caso le dejé el que tenia por omisión que es "listView1"

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    
     <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>
</RelativeLayout>

2.- Ahora lo que necesitamos es un "Contenedor" que nos permita guardar la información de cada elemento a mostrar dentro de cada celda del ListView, es un simple Clase con dos String que seran titulo y subtitulo respectivamente y un tipo int para guardar un ID de imagen en este caso utilizaremos imágenes que estén dentro del proyecto, por eso el int para el ID,l la clase quedaría algo mas o menos así, en mi caso la nombré "ElementList"

public class ElementList {

public String title;
public String subTitle;
public int image;

public ElementList(String title, String subtitle, int Image) {

setTitle(title);
setSubTitle(subtitle);
setImage(Image);
}

public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSubTitle() {
return subTitle;
}
public void setSubTitle(String subTitle) {
this.subTitle = subTitle;
}
public int getImage() {
return image;
}
public void setImage(int image) {
this.image = image;
}
}

Nota: Para agregarle los Getters y Setters de manera rápida, colocamos el cursor dentro de nuestra clase principal, damos click en "Source" dentro de la barra de herramientas y seleccionamos "Generate getters and setters", seleccionamos las variables que queremos generar y damos ok, se habrán generado de manera automatica todos los getters y setter que indicamos.

3.- Ahora necesitamos una vista personalizada que definirá cada celda que vamos a utilizar dentro del listView, de manera facil creamos dentro de la carpeta "res/layout " un nuevo archivo XML y le agregamos los siguientes elementos con sus respectivos ID

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/listImageView"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_weight="1"
        android:src="@drawable/ic_launcher" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="55dp"
        android:layout_marginLeft="5dp"
        android:layout_weight=".5"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/listTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Titulo"
            android:textAppearance="?android:attr/textAppearanceLarge" />

        <TextView
            android:id="@+id/listSubtitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Subtitulo" />

    </LinearLayout>


</LinearLayout>

Con esto notaremos en el modo gráfico, que hemos creado un celda con una imagen un titulo y un subtitulo, ahora solo necesitamos indicar a nuestro activity, que queremos que use este modelo, en vez de los modelos que tiene por default.


4.- Bueno ahora lo siguiente será crear nuestro "Adaptador" personalizado, que nos permita unir  nuestro Activity principal a los elementos que componen a nuestro ListView que estamos creando, para hacerlo Vamos al navegador de paquetes, damos click derecho sobre el paquete en el que queremos insertar nuestra nueva clase > new > Class , nos abrira una ventana nueva daremos un nombre a la nueva clase que en mi caso le puse MiAdapter, e indicamos que hereda parametros de la clase BaseAdapter, mas o menos asi...

Una vez creada, le vamos a agregar las variables que necesitamos que son, el contexto de la aplicación, y una lista de ElemetList (la clase contenedora creada previamente).

public class MiAdapter extends BaseAdapter {

    private Context context;
    private List<ElementList> items;
    
    public MiAdapter(Context context, List<ElementList> items) 
    {
    super();
        this.context = context;
        this.items = items;
    }
}

Como podemos Ver en eclipse, el compilador nos da un error, y eso es porque esta clase, necesita de ciertos métodos que tenemos que sobrescribir, vamos al icono de error con un foquito a la izquierda del código, damos click y seleccionamos "Add unimplemented metods"

Una vez agregados los metodos necesarios, los vamos a adaptar a lo que estamos haciendo a continuación explicamos cada parte de código atraves de comentarios.

public class MiAdapter extends BaseAdapter {

    private Context context;
    private List<ElementList> items;
    
    public MiAdapter(Context context, List<ElementList> items) 
    {
    super(); //superConstructor de la clase base
        this.context = context;// contexto de la app
        this.items = items;// elementos enviados para mostrar en el ListView
    }
    
//este metodo nos devuelve el numero de elementos que tiene nuestro ListView
@Override
public int getCount() 
{
return items.size();
}

/*Este método nos devuelve el objeto como tal según el indice que le enviemos como parámetro*/
@Override
public Object getItem(int arg0) 
{
return items.get(arg0);
}

/*este método nos devuelve el id del objeto según el indice que le pasemos como parametro*/
@Override
public long getItemId(int arg0) 
{
return arg0;
}

/*este método es el encargado de crear cada celda o fila del ListView, nunca usaremos el método manualmente ya que el adaptador lo hará solo, recibe como parametros el indice del elemento actual, la vista que construirá o reutilizará y el grupo de vistas al que pertenece*/
@Override
public View getView(int arg0, View arg1, ViewGroup arg2)
{
View tempView = arg1;
 

/*Se utiliza este if para reutilizar vistas y gastar la menos cantidad de memoria posible, si la vista ya existe no la crea de nuevo*/
        if (arg1 == null) {
            // Creamos una nueva vista dentro del listView.
            LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

/*le indicamos que utilice el layout creado previamente para cada celda*/
            tempView = inflater.inflate(R.layout.mi_list_view, arg2, false);
        }
        /*creamos las referencias del layout de la vista personalizada de cada celda*/

        ImageView imageItem = (ImageView) tempView.findViewById(R.id.listImageView);
        TextView titleItem = (TextView) tempView.findViewById(R.id.listTitle);
        TextView subtitleItem = (TextView) tempView.findViewById(R.id.listSubtitle);

/*asignamos los valores de titulo, subtitulo, e imagen a cada elemento de la lista*/

        ElementList item = this.items.get(arg0);
        titleItem.setText(item.getTitle());
        subtitleItem.setText(item.getSubTitle());
        imageItem.setImageResource(item.getImage());
        
        return tempView; //devolvemos la vista modificada
}

}

5.- Genial, ya tenemos todos los elementos para que nuestro ListView funcione perfectamente, ahora lo que necesitamos es implementar todo lo creado anteriormente y eso, lo lograremos en nuestro activity principal, aquí el código comentado.

public class ListViewActivity extends Activity {
ListView myListView;
private static final int AMOUNT = 100;

@Override
protected void onCreate(Bundle savedInstanceState) 
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_view);
initInterfaz ();
/*indicamos que se le asigna un adaptador a nuestro objeto ListView, lo inicializamos
* con la palabra reservada new, y lo que pide nuestro adaptador personalizado en su constructor
* es el contexto de la app y un list , el list se crea con otro metodo, que se encuentra mas abajo
*/
myListView.setAdapter(new MiAdapter(getApplicationContext(), createList()));
/*
* una vez hecho los pasos anteriores nuestro listView ya funciona perfectamente, pero queremos que al tocarlo 
* nos lance a otro activity, para eso utilizaremos la interfaz setOnItemClickListener del objeto AdapterView
*/
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {

Intent myIntent = new Intent(ListViewActivity.this, SecondActivity.class);
/*
* enviamos como parametro entre activities el numero de fila tocado que en este caso es arg2
* y lanzamos el activity
*/
myIntent.putExtra("row", arg2);
startActivity(myIntent);
}
});
}

private void initInterfaz()
{
myListView = (ListView) findViewById(R.id.listView1);
}
private List<ElementList> createList ()
{
List<ElementList> elements = new ArrayList<ElementList>();
/*
* se puede observar que se crean muchos elementos de manera dinamica con fines de ejemplo
* el titulo ira de 0 a 99 y el subtitulo siempre sera el numero de elementos que se crearon
* el icono es el mismo, que es el icono de la app, 
*/
for (int i = 0; i < AMOUNT; i++) 
{
elements.add(new ElementList("Titulo "+ i,"Subtitulo "+ AMOUNT, R.drawable.ic_launcher));
}
return elements;
}
}

Ahora la aplicación esta lista para mostrar los elementos del ListView corremos la aplicación y veremos cosas como esta. Se nota que el uso del ListView es mas potente que el uso de un TableLayout, pero a la vez un poco mas complejo

Ojalá les sirva y les guste. Saludos




No hay comentarios.:

Publicar un comentario