jueves, 19 de diciembre de 2013

Agregar TableRow's dinámicamente a un TableLayout

Tratando de dar continuidad a mi blog voy a escribir sobre un tema mucho mas común que el anterior: Agregar filas dinámicamente a un TableLayout.

Primero creamos un .xml en la carpeta res/layout con la estructura que ha de tener cada una de las filas a agregar, en mi caso la fila debe tener tres columnas, la primera con una etiqueta para un número secuencial, la segunda con un signo de pesos y una etiqueta para un monto y la tercera con una etiqueta para una fecha.

he nombrado a mi archivo row_repayment_plan.xml y el contenido es el siguiente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <TextView
        android:id="@+id/index"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="@drawable/rectangle_border"
        android:gravity="center"
        android:paddingBottom="5dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:paddingTop="5dp"
        android:textAppearance="?android:attr/textAppearanceSmall" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="@drawable/rectangle_border" >
        
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="left"
            android:paddingBottom="5dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:paddingTop="5dp"
            android:text="$"
            android:textAppearance="?android:attr/textAppearanceSmall" />
        
        <TextView
            android:id="@+id/amount"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="right"
            android:paddingBottom="5dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:paddingTop="5dp"
            android:textAppearance="?android:attr/textAppearanceSmall" />

    </LinearLayout>

    <TextView
        android:id="@+id/date"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="@drawable/rectangle_border"
        android:gravity="center"
        android:paddingBottom="5dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:paddingTop="5dp"
        android:textAppearance="?android:attr/textAppearanceSmall" />

</TableRow>

Notese el uso de android:background="@drawable/rectangle_border", es un archivo .xml para ponerle un borde rectangular a cada "celda".

Para esto se crea el archivo rectangle_border.xml en la carpeta res/drawable con el siguiente contenido:

1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
  xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@android:color/transparent" />
    <stroke android:width="1.0dip" android:color="#ff000000" />
</shape>

También usamos la propiedad android:layout_weight, esta sirve para distribuir el espacio de la fila, en este caso las tres columnas tendran el mismo ancho, por eso tenemos android:layout_weight="1" en los tres casos, para que esta propiedad funcione correctamente debemos tener android:layout_width="0dp"

 Después incluimos en el xml de nustro activity el TableLayout al que vamos a agregarle filas con un código como el siguiente:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
         <TableLayout
            android:id="@+id/repaymentTable"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >

            <TableRow
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/DarkGray" >

                <TextView
                    android:id="@+id/index"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/rectangle_border"
                    android:gravity="center"
                    android:paddingBottom="5dp"
                    android:paddingLeft="10dp"
                    android:paddingRight="10dp"
                    android:paddingTop="5dp"
                    android:text="@string/number_of_payments"
                    android:textAppearance="?android:attr/textAppearanceSmall"
                    android:textColor="@color/White"
                    android:textColorLink="@color/White" />

                <TextView
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/rectangle_border"
                    android:gravity="center"
                    android:paddingBottom="5dp"
                    android:paddingLeft="10dp"
                    android:paddingRight="10dp"
                    android:paddingTop="5dp"
                    android:text="@string/amount_of_payment"
                    android:textAppearance="?android:attr/textAppearanceSmall"
                    android:textColor="@color/White" />

                <TextView
                    android:id="@+id/date"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/rectangle_border"
                    android:gravity="center"
                    android:paddingBottom="5dp"
                    android:paddingLeft="10dp"
                    android:paddingRight="10dp"
                    android:paddingTop="5dp"
                    android:text="@string/scheduled_payment_date"
                    android:textAppearance="?android:attr/textAppearanceSmall"
                    android:textColor="@color/White" />

            </TableRow>
        </TableLayout>

Este TableLayout ya contiene un TableRow que hará las veces de cabecera de la tabla, con la misma estructura que el TableRow que agregaremos dinámicamente.

Por último en el .java de nustro activity ponemos el código que agregará las filas:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
                try {
			
			Intent actualIntent = getIntent();
			
			JSONArray payments = new JSONArray(actualIntent.getStringExtra("payments"));

			TableLayout table = (TableLayout) this.findViewById(R.id.repaymentTable);

			for (int i = 0; i < payments.length(); i++) {

				TableRow row = (TableRow) LayoutInflater.from(this).inflate(R.layout.row_repayment_plan, null);
				
				if(i % 2 != 0) {
					
					row.setBackgroundColor(Color.LTGRAY);
				}

				((TextView) row.findViewById(R.id.index)).setText(Integer.toString(i + 1));
				((TextView) row.findViewById(R.id.amount)).setText(payments.getJSONObject(i).getString("amount"));
				((TextView) row.findViewById(R.id.date)).setText(payments.getJSONObject(i).getString("date"));
					
				table.addView(row);
			}
		} catch (JSONException exception) {
			
			Logger4J.error(getClass(), exception.getMessage());
		}

En mi caso la información que se va a poner en la tabla llega como un extra del Intent, con la llave payments.

El valor de este extra es un arreglo de objetos JSON como el siguiente:

[{"amount": "115.10", "date": "02/10/2013"}, {"amount": "115.10", "date": "02/12/2013"}, {"amount": "115.10", "date": "02/14/2013"}, {"amount": "115.10", "date": "02/16/2013"}]

Esta forma de poner los datos es opcional, se puede usar cualquier colección que convenga a sus necesidades.

Luego se recorre la colección de datos y por cada elemento se crea un TableRow a partir de la plantilla que creamos previamente, en este caso identificada por R.layout.row_repayment_plan


De esa plantilla extraemos los TextView's y les asignamos el valor que les corresponda.

He usado el índice i para poner fondo gris claro a las filas impares.

Al final agregamos la fila a la tabla con table.addView(row);


Espero que esto les sea de utilidad.

Gracias y saludos!!