1. Code
  2. Mobile Development
  3. Android Development

Diseño de Interfaz de Usuario Android: Tabla de Composiciones

Table layouts, puede user utilizado para mostrar datos de forma tabular o bien, alineando los contenidos en la pantalla en una forma similar a una tabla HTML en una página web. Aprenda cómo crearlas con los archivos layout XML y a través del código. Entender los Layouts es importante para el buen diseño de la aplicación Android. En este tutorial, aprenderá todo sobre las tablas layouts, las cuales organizan los controles de la interfaz de usuario, o widgets, en la pantalla, prácticamente en filas y columnas definidas. Cuando se usan correctamente, los tablas layouts pueden ser potentes paradigmas sobre las que pueden ser diseñadas sus pantallas o mostrar los datos de forma tabular.
Scroll to top
This post is part of a series called Android User Interface Design.
Android UI Fundamentals Challenge: RelativeLayout
Android User Interface Design: Frame Layouts

Spanish (Español) translation by Rodney Martinez (you can also view the original English article)

Table layouts, puede user utilizado para mostrar datos de forma tabular o bien, alineando los contenidos en la pantalla en una forma similar a una tabla HTML en una página web. Aprenda cómo crearlas con los archivos layout XML y a través del código.

Entender los Layouts es importante para el buen diseño de la aplicación Android. En este tutorial, aprenderá todo sobre las tablas layouts, las cuales organizan los controles de la interfaz de usuario, o widgets, en la pantalla, prácticamente en filas y columnas definidas. Cuando se usan correctamente, los tablas layouts pueden ser potentes paradigmas sobre las que pueden ser diseñadas sus pantallas o mostrar los datos de forma tabular.

¿Qué es una Table Layout?

Una table layout es, exactamente, lo que se podría esperar: una cuadrícula hecha de filas y columnas, en donde una celda puede mostrar un control vista. Desde la perspectiva de diseño de una interfaz de usuario, una TableLayout está compuesta de controles TableRow —uno para cada fila en su tabla. Los contenidos de una TableRow son simplemente controles view que lo irán en cada "celda" de la tabla.

La apariencia de una TableLayout está regida por varias reglas adicionales. Primero, el número de columnas de toda la tabla coincide con el número de columnas en la fila con la mayoría de las columnas. Segundo, el ancho de cada columna está definido como el ancho del contenido más amplio en la columna. Las filas child del TableLayout y las celdas de los atributos layout_width siempre están en MATCH_PARENT -- aunque no se pueden poner en un archivo XML, el valor actual no puede ser anulado. El parámetro layout_height de la TableLayout de una celda puede ser definido, sin embargo, un atributo TableRow para layout_height está siempre WRAP_CONTENT. Las celdas pueden abarcar columnas, pero no filas. Esto se hace a través del atributo layout_span de la vista child de una TableRow. Una celda es una sola vista child dentro de una TableRow. Si quiere una celda más compleja con múltiples vistas, use una vista layout para encapsular las otras vistas.

Dicho eso, algunas reglas pueden ser modificadas. Las columnas pueden ser marcadas como estirables, lo que significa que el ancho se puede expandir al tamaño del contenedor parent. También, las columnas pueden ser marcadas como encogibles, lo que significa que pueden ser reducidas en anchura para que la fila entera encaje en el lugar proporcionado por el contenedor parent.

Para la documentación completa para la table layouts, vea la documentación Android SDK para la clase TableLayout. El atributo XML asociado para usar en XML resource, también, está definido en la documentación.

Diseñando un Simple Table Layout

Los layouts, se explican mejor con ejemplos, y los table layout no son diferentes. Digamos que queremos diseñar una pantalla que muestra el pronóstico del tiempo ampliado. Una table layout podría ser una buena opción para organizar esta información:

  • En la primer TableRow, podemos mostrar un título para la pantalla.
  • En la segunda TableRow, podemos mostrar las fechas en un formato familiar como el de un calendario.
  • En la tercera TableRow, podemos mostrar una información para la temperatura Más Alta Diariamente.
  • En la cuarta TableRow, podemos mostrar una información de temperatura Diaria Baja.
  • En la quinta TableRow, podemos mostrar gráficos para identificar las condiciones del clima, tales como lluvia, nieve, sol, nublado con una probabilidad de pelotas.

La primera figura muestra un vistazo en la tabla dentro del editor layout:

Android SDK - Table Layouts - Figure 1Android SDK - Table Layouts - Figure 1Android SDK - Table Layouts - Figure 1

Definiendo un XML Layour Resource con un Table Layout

La manera más conveniente y sostenible de diseñar una aplicación de interfaz de usuario es por medio de la creación de XML layout resources. Este método simplifica mucho el proceso de diseño UI, moviéndose de la creación static y layout de los controles de interfaz de usuario y la definición de los controles de los atributos,  hacia el XML, en lugar de las letras de código.

XML layout resource, deben ser guardados en la jerarquía del directorio del proyecto: /res/layout. Vamos a echar un vistazo a los table layout presentados en la sección anterior. Este archivo layout resource, nombrado convenientemente como /res/layout/table.xml, está definido en XML como sigue:

1
 
2
<?xml version="1.0" encoding="utf-8"?>
3
<TableLayout
4
    xmlns:android="http://schemas.android.com/apk/res/android"
5
    android:id="@+id/tableLayout1"
6
    android:layout_width="match_parent"
7
    android:layout_height="match_parent"
8
    android:shrinkColumns="*"
9
    android:stretchColumns="*">
10
    <TableRow
11
        android:id="@+id/tableRow4"
12
        android:layout_height="wrap_content"
13
        android:layout_width="match_parent"
14
        android:gravity="center_horizontal">
15
        <TextView
16
            android:id="@+id/textView9"
17
            android:layout_width="match_parent"
18
            android:layout_height="wrap_content"
19
            android:textStyle="bold"
20
            android:typeface="serif"
21
            android:textSize="18dp"
22
            android:text="Weather Table"
23
            android:gravity="center"
24
            android:layout_span="6"></TextView>
25
    </TableRow>
26
    <TableRow
27
        android:id="@+id/tableRow1"
28
        android:layout_height="wrap_content"
29
        android:layout_width="match_parent">
30
        <TextView
31
            android:id="@+id/TextView04"
32
            android:text=""></TextView>
33
        <TextView
34
            android:id="@+id/TextView04"
35
            android:text="Feb 7"
36
            android:textStyle="bold"
37
            android:typeface="serif"></TextView>
38
        <TextView
39
            android:id="@+id/TextView03"
40
            android:text="Feb 8"
41
            android:textStyle="bold"
42
            android:typeface="serif"></TextView>
43
        <TextView
44
            android:id="@+id/TextView02"
45
            android:text="Feb 9"
46
            android:textStyle="bold"
47
            android:typeface="serif"></TextView>
48
        <TextView
49
            android:id="@+id/TextView01"
50
            android:text="Feb 10"
51
            android:textStyle="bold"
52
            android:typeface="serif"></TextView>
53
        <TextView
54
            android:text="Feb 11"
55
            android:id="@+id/textView1"
56
            android:textStyle="bold"
57
            android:typeface="serif"></TextView>
58
    </TableRow>
59
    <TableRow
60
        android:layout_height="wrap_content"
61
        android:id="@+id/tableRow2"
62
        android:layout_width="match_parent">
63
        <TextView
64
            android:text="Day High"
65
            android:id="@+id/textView2"
66
            android:textStyle="bold"></TextView>
67
        <TextView
68
            android:id="@+id/textView3"
69
            android:text="28°F"
70
            android:gravity="center_horizontal"></TextView>
71
        <TextView
72
            android:text="26°F"
73
            android:id="@+id/textView4"
74
            android:gravity="center_horizontal"></TextView>
75
        <TextView
76
            android:text="23°F"
77
            android:id="@+id/textView5"
78
            android:gravity="center_horizontal"></TextView>
79
        <TextView
80
            android:text="17°F"
81
            android:id="@+id/textView6"
82
            android:gravity="center_horizontal"></TextView>
83
        <TextView
84
            android:text="19°F"
85
            android:id="@+id/textView7"
86
            android:gravity="center_horizontal"></TextView>
87
    </TableRow>
88
    <TableRow
89
        android:layout_height="wrap_content"
90
        android:id="@+id/tableRow2"
91
        android:layout_width="match_parent">
92
        <TextView
93
            android:text="Day Low"
94
            android:id="@+id/textView2"
95
            android:textStyle="bold"></TextView>
96
        <TextView
97
            android:text="15°F"
98
            android:id="@+id/textView3"
99
            android:gravity="center_horizontal"></TextView>
100
        <TextView
101
            android:text="14°F"
102
            android:id="@+id/textView4"
103
            android:gravity="center_horizontal"></TextView>
104
        <TextView
105
            android:text="3°F"
106
            android:id="@+id/textView5"
107
            android:gravity="center_horizontal"></TextView>
108
        <TextView
109
            android:text="5°F"
110
            android:id="@+id/textView6"
111
            android:gravity="center_horizontal"></TextView>
112
        <TextView
113
            android:text="6°F"
114
            android:id="@+id/textView7"
115
            android:gravity="center_horizontal"></TextView>
116
    </TableRow>
117
    <TableRow
118
        android:id="@+id/tableRow3"
119
        android:layout_height="wrap_content"
120
        android:layout_width="match_parent"
121
        android:gravity="center">
122
        <TextView
123
            android:id="@+id/textView8"
124
            android:text="Conditions"
125
            android:textStyle="bold"></TextView>
126
        <ImageView
127
            android:id="@+id/imageView1"
128
            android:src="@drawable/hot"></ImageView>
129
        <ImageView
130
            android:id="@+id/imageView2"
131
            android:src="@drawable/pt_cloud"></ImageView>
132
        <ImageView
133
            android:id="@+id/imageView3"
134
            android:src="@drawable/snow"></ImageView>
135
        <ImageView
136
            android:id="@+id/imageView4"
137
            android:src="@drawable/lt_snow"></ImageView>
138
        <ImageView
139
            android:id="@+id/imageView5"
140
            android:src="@drawable/pt_sun"></ImageView>
141
    </TableRow>
142
</TableLayout>

Recuerde que, desde la parte interna del Activity, solamente una sola línea de código dentro del método onCreate() es necesaria para cargar y mostrar un layout resource en la pantalla.

1
 
2
setContentView(R.layout.table);

Esta table layout tiene todas sus columnas ajustadas tanto para reducirse como para estirarse usando un "*" en el valor. Si ciertas columnas deberían reducirse o estirarse, entonces los valores serían separados por una coma (usando 0 como la base para el índice para las columnas).

La tabla ahora luce como se ve en la siguiente captura de pantalla cuando está en modo vertical u horizontal.

Android SDK - Table Layouts - Figure 2 - LandscapeAndroid SDK - Table Layouts - Figure 2 - LandscapeAndroid SDK - Table Layouts - Figure 2 - Landscape
Android SDK - Table Layouts - Figure 2 - PortraitAndroid SDK - Table Layouts - Figure 2 - PortraitAndroid SDK - Table Layouts - Figure 2 - Portrait

Definiendo una Table Layout por medio de programación

También puede crear por medio de programación y configurar table layouts en Java. Esto se hace usando las clases TableLayout y TableRow (android.widget.TableLayout y android.widget.TableRow). Encontrará los únicos parámetros mostrados para cada controle en las clases TableLayout.LayoutParams y TableRow.LayoutParams. Asimismo, los parámetros normales  (android.view.ViewGroup.LayoutParams), tales como layout_height y layout_width, así como también los parámetros de los márgenes (ViewGroup.MarginLayoutParams), aún se utilizan en los objetos TableLayout. Para las celdas de las tablas (cualquier View dentro de la TableRow), la anchura siempre es MATCH_PARENT. La altura puede ser definida, pero por defecto será WRAP_CONTENT y no necesita ser especificada.
En vez de cargar un layout resource directamente usando el método setContentView() como se mostró anteriormente, si usted crea un layout por medio de la programación, en lugar de eso de desarrollar la pantalla de contenidos en Java y luego proporcionar un objeto parent layout que contiene los controles de contenidos para mostrar como child views para el método setContentView(). En este caso, su parent layout utilizado sería el table layout creado.

Por ejemplo, el siguiente código ilustra cómo por medio de programación una instancia Activity tiene un parámetro layout TableLayout y reproduce el ejemplo demostrado anteriormente en XML:

1
2
    @Override
3
    public void onCreate(Bundle savedInstanceState) {
4
        super.onCreate(savedInstanceState);
5
6
        TableLayout table = new TableLayout(this);
7
8
        table.setStretchAllColumns(true);
9
        table.setShrinkAllColumns(true);
10
11
        TableRow rowTitle = new TableRow(this);
12
        rowTitle.setGravity(Gravity.CENTER_HORIZONTAL);
13
14
        TableRow rowDayLabels = new TableRow(this);
15
        TableRow rowHighs = new TableRow(this);
16
        TableRow rowLows = new TableRow(this);
17
        TableRow rowConditions = new TableRow(this);
18
        rowConditions.setGravity(Gravity.CENTER);
19
20
        TextView empty = new TextView(this);
21
22
        // title column/row
23
        TextView title = new TextView(this);
24
        title.setText("Java Weather Table");
25
26
        title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
27
        title.setGravity(Gravity.CENTER);
28
        title.setTypeface(Typeface.SERIF, Typeface.BOLD);
29
30
        TableRow.LayoutParams params = new TableRow.LayoutParams();
31
        params.span = 6;
32
33
        rowTitle.addView(title, params);
34
35
        // labels column
36
        TextView highsLabel = new TextView(this);
37
        highsLabel.setText("Day High");
38
        highsLabel.setTypeface(Typeface.DEFAULT_BOLD);
39
40
        TextView lowsLabel = new TextView(this);
41
        lowsLabel.setText("Day Low");
42
        lowsLabel.setTypeface(Typeface.DEFAULT_BOLD);
43
44
        TextView conditionsLabel = new TextView(this);
45
        conditionsLabel.setText("Conditions");
46
        conditionsLabel.setTypeface(Typeface.DEFAULT_BOLD);
47
48
        rowDayLabels.addView(empty);
49
        rowHighs.addView(highsLabel);
50
        rowLows.addView(lowsLabel);
51
        rowConditions.addView(conditionsLabel);
52
53
        // day 1 column
54
        TextView day1Label = new TextView(this);
55
        day1Label.setText("Feb 7");
56
        day1Label.setTypeface(Typeface.SERIF, Typeface.BOLD);
57
58
        TextView day1High = new TextView(this);
59
        day1High.setText("28°F");
60
        day1High.setGravity(Gravity.CENTER_HORIZONTAL);
61
62
        TextView day1Low = new TextView(this);
63
        day1Low.setText("15°F");
64
        day1Low.setGravity(Gravity.CENTER_HORIZONTAL);
65
66
        ImageView day1Conditions = new ImageView(this);
67
        day1Conditions.setImageResource(R.drawable.hot);
68
69
        rowDayLabels.addView(day1Label);
70
        rowHighs.addView(day1High);
71
        rowLows.addView(day1Low);
72
        rowConditions.addView(day1Conditions);
73
74
        // day2 column
75
        TextView day2Label = new TextView(this);
76
        day2Label.setText("Feb 8");
77
        day2Label.setTypeface(Typeface.SERIF, Typeface.BOLD);
78
79
        TextView day2High = new TextView(this);
80
        day2High.setText("26°F");
81
        day2High.setGravity(Gravity.CENTER_HORIZONTAL);
82
83
        TextView day2Low = new TextView(this);
84
        day2Low.setText("14°F");
85
        day2Low.setGravity(Gravity.CENTER_HORIZONTAL);
86
87
        ImageView day2Conditions = new ImageView(this);
88
        day2Conditions.setImageResource(R.drawable.pt_cloud);
89
90
        rowDayLabels.addView(day2Label);
91
        rowHighs.addView(day2High);
92
        rowLows.addView(day2Low);
93
        rowConditions.addView(day2Conditions);
94
95
        // day3 column
96
        TextView day3Label = new TextView(this);
97
        day3Label.setText("Feb 9");
98
        day3Label.setTypeface(Typeface.SERIF, Typeface.BOLD);
99
100
        TextView day3High = new TextView(this);
101
        day3High.setText("23°F");
102
        day3High.setGravity(Gravity.CENTER_HORIZONTAL);
103
104
        TextView day3Low = new TextView(this);
105
        day3Low.setText("3°F");
106
        day3Low.setGravity(Gravity.CENTER_HORIZONTAL);
107
108
        ImageView day3Conditions = new ImageView(this);
109
        day3Conditions.setImageResource(R.drawable.snow);
110
111
        rowDayLabels.addView(day3Label);
112
        rowHighs.addView(day3High);
113
        rowLows.addView(day3Low);
114
        rowConditions.addView(day3Conditions);
115
116
        // day4 column
117
        TextView day4Label = new TextView(this);
118
        day4Label.setText("Feb 10");
119
        day4Label.setTypeface(Typeface.SERIF, Typeface.BOLD);
120
121
        TextView day4High = new TextView(this);
122
        day4High.setText("17°F");
123
        day4High.setGravity(Gravity.CENTER_HORIZONTAL);
124
125
        TextView day4Low = new TextView(this);
126
        day4Low.setText("5°F");
127
        day4Low.setGravity(Gravity.CENTER_HORIZONTAL);
128
129
        ImageView day4Conditions = new ImageView(this);
130
        day4Conditions.setImageResource(R.drawable.lt_snow);
131
132
        rowDayLabels.addView(day4Label);
133
        rowHighs.addView(day4High);
134
        rowLows.addView(day4Low);
135
        rowConditions.addView(day4Conditions);
136
137
        // day5 column
138
        TextView day5Label = new TextView(this);
139
        day5Label.setText("Feb 11");
140
        day5Label.setTypeface(Typeface.SERIF, Typeface.BOLD);
141
142
        TextView day5High = new TextView(this);
143
        day5High.setText("19°F");
144
        day5High.setGravity(Gravity.CENTER_HORIZONTAL);
145
146
        TextView day5Low = new TextView(this);
147
        day5Low.setText("6°F");
148
        day5Low.setGravity(Gravity.CENTER_HORIZONTAL);
149
150
        ImageView day5Conditions = new ImageView(this);
151
        day5Conditions.setImageResource(R.drawable.pt_sun);
152
153
        rowDayLabels.addView(day5Label);
154
        rowHighs.addView(day5High);
155
        rowLows.addView(day5Low);
156
        rowConditions.addView(day5Conditions);
157
158
        table.addView(rowTitle);
159
        table.addView(rowDayLabels);
160
        table.addView(rowHighs);
161
        table.addView(rowLows);
162
        table.addView(rowConditions);
163
164
        setContentView(table);
165
166
    }

Vamos a echar un vistazo más de cerca al código anterior de Java. Primero, creamos un control TableLayout y configuramos los atributos encogible y estirable en true para todas las columnas usando los métodos setStretchAllColumns() y setShrinkAllColumns(). Después, sistemáticamente creamos cinco TableRow. Cada TableRow contendrá controles view (los controles TextView para el título, fechas, datos así como también controles ImageView para los gráficos de las condiciones del clima). Verá como la columna expandida está controlada con el primer TableRow. Específicas columnas de views son creadas, arregladas, para el apropiado TableRow usando el método addView(). Cada TableRow es agregado al control TableLayout, en orden, usando el método addView() del TableLayout. Finalmente, cargamos el TableLayout y lo mostramos en la pantalla usando el método setContentView().

Como puede ver, el código puede rápidamente aumentar en tamaño en la medida que más controles son añadidos a la pantalla. Para la organización y mantenimiento, definiendo y usando layouts por medio de programación lo mejor que queda para algún caso es la norma. De manera adicional, en un caso como éste, los datos normalmente vendrían de parte de alguna otra fuente que los strings que  escribimos, por lo que un ciclo puede ser más apropiado para muchas aplicaciones.

Los resultados se muestran en la siguiente imagen. Como puede ver, son los mismos resultados que mostramos anteriormente, tal y como se esperaba.

Android SDK - Table Layouts - Figure 3 - PortraitAndroid SDK - Table Layouts - Figure 3 - PortraitAndroid SDK - Table Layouts - Figure 3 - Portrait

Inquietudes acerca de las TableLayout

Aunque las table layouts pueden ser utilizadas para diseñar interfaz de usuarios enteras, en realidad, no son la mejor herramienta para hacer eso, como son derivadas de las LinearLayout y no de los controles layout más eficientes. Si piensa en ello, un TableLayout es más que organizar un conjunto de LinearLayouts anidados, y los layouts anidados demasiado son generalmente desestimado en lo que concierne a rendimiento. Sin embargo, para datos que ya están en un formato adecuado para una tabla, tales como datos de hojas de cálculo, los table layout pueden ser una opción razonable.

Además, los datos table layout pueden varia dependiendo de los tamaños de pantalla y resoluciones. Es, generalmente, una buena práctica de diseño para garantizarle la habilidad de desplazarse cuando muestre grandes cantidades de datos. Por ejemplo, si el ejemplo del clima que usamos anteriormente, incluye una de las condiciones "redactar", este texto podría ser una oración o veinte oraciones, así que activar el desplazamiento vertical u horizontal sería lo más prudente.

En conclusión

La aplicación de interfaz de usuario Android está definidas usando layouts, y los table layout son increíblemente prácticos para mostrar vista de datos o controles en filas y columnas. Usando la table layout donde son más adecuadas puede hacer que muchos diseños de pantalla sean más sencillos y rápidos. Sin embargo, tenga en cuenta que los TableLayout son derivados de los LinearLayout, y tienen muchas de las limitaciones de rendimiento que tienen estos.

Acerca de los Autores

Desarrolladores de Celulares; Lauren Darcey y Shane Conder son coautores de varios libros sobre el desarrollo en Android: un libro de programación a fondo titulado: Desarrollo de Aplicaciones Inalámbricas de Android y Sams Aprenda usted mismo a Desarrollar Aplicaciones para Android en 24 horas. Cuando no escriben, ellos pasan su tiempo desarrollando programas para celulares en sus empresas y proporcionando servicios de consultoría. Pueden ser localizado a través de correo electrónico: androidwirelessdev+mt@gmail.com o por medio de su blog en androidbook.blogspot.com y en Twitter @androidwireless.

¿Necesita más ayuda escribiendo aplicaciones de Android? ¡Revise nuestros últimos libros y recursos!

Buy Android Wireless Application Development, 2nd Edition Buy Sam's Teach Yourself Android Application Development in 24 Hours Mamlambo code at Code Canyon