Uso
de tabs (pestañas)
Los tabs nos van a permitir crear una interfaz de usuario basada en
pestañas, donde, de una forma muy intuitiva, podemos ofrecer al
usuario diferentes vistas, que son seleccionadas al pulsar una de
las pestañas que se muestran en la parte superior:
Para crear una interfaz de usuario con pestañas, es necesario
utilizar FragmentTabHost y TabWidget. FragmentTabHost debe ser
el nodo raíz para el diseño, que contendrá tanto el TabWidget para
la visualización de las pestañas, como un FrameLayout para
mostrar el contenido. A continuación se muestra el esquema a
utilizar:
Nota: En las primeras versiones de Android se usaba TabHosten
lugar de FragmentTabHost. A partir del nivel de API
13, TabHost ha sido declarado obsoleto. Google ha reorientado su
jerarquía de clases para introducir el concepto de fragment. No
obstante, puedes seguir utilizando TabHost sin ningún problema.
Nota: Hasta la vesión 3.0 (API 11) no aparece FragmentTabHost.
Entonces, no podría usarse en niveles de API anteriores. Para
resolver este problema, y más generalmente para poder usar
fragments en versiones anteriores a la 3.0, Google ha creado la
librería de compatibilidad[1] (android.support). Se añade por
defecto al crear un nuevo proyecto. Por lo tanto, podemos usar
fragments y clases relacionadas desde cualquier versión.
1. <android.support.v4.app.FragmentTabHost
2. android:id="@android:id/tabhost" …/>
3. <LinearLayout …>
4. <TabWidget
5. android:id="@android:id/tabs" …/>
6. <FrameLayout
7. android:id="@android:id/tabcontent" …>
8. </LinearLayout>
9. </TabHost>
Nota: El siguiente vídeo utiliza TabHost en
lugar FragmentTabHost. No obstante, los conceptos que se
explican siguen siendo válidos.
Ejercicio paso a paso: Uso de FragmentTabHost
1. Crea un nuevo proyecto y llámalo Tabs.
2. Reemplaza el código de activity_main.xml por el siguiente:
1. <android.support.v4.app.FragmentTabHost
2. xmlns:android="http://schemas.android.com/apk/res/android"
3. android:id="@android:id/tabhost"
4. android:layout_width="match_parent"
5. android:layout_height="match_parent" >
6. <LinearLayout
7. android:layout_width="match_parent"
8. android:layout_height="match_parent"
9. android:orientation="vertical" >
10. <TabWidget
11. android:id="@android:id/tabs"
12. android:layout_width="match_parent"
13. android:layout_height="wrap_content"
14. android:layout_weight="0"
15. android:orientation="horizontal" />
16. <FrameLayout
17. android:id="@android:id/tabcontent"
18. android:layout_width="match_parent"
19. android:layout_height="0dp"
20. android:layout_weight="1" />
21. </LinearLayout>
22. </android.support.v4.app.FragmentTabHost>
La primera cosa extraña de este código es el nombre de la primera
etiqueta. En lugar de indicar simplemente FragmentTabHost, se ha
indicado el nombre completo de domínio. Como estudiaremos en el
capítulo 4, cada vez que usemos una vista que no sea del sistema
(por ejemplo creada por nosotros o creada en una librería como en
este caso) tendremos que indicar la clase donde se crea con su
nombre completamente cualificado. Es decir, el nombre de la clase
precedida de su paquete.
Como puedes observar un FragmentTabHost es el nodo raíz del
diseño, que contiene dos elementos combinados por medio de
un LinearLayout. El primero es un TabWidget para la visualización
de las pestañas y el segundo es un FragmentLayout para mostrar el
contenido asociado de cada lengüeta. En número de lengüetas y su
contenido se indicará por código.
3. Abre el fichero MainActivity.java y reemplaza el código por el
siguiente:
1. import android.os.Bundle;
2. import android.support.v4.app.FragmentActivity;
3. import android.support.v4.app.FragmentTabHost;
4.
5. publicclassMainActivity extendsFragmentActivity {
6.
7. privateFragmentTabHost tabHost;
8.
9. @Override
10. protectedvoidonCreate(Bundle savedInstanceState) {
11. super.onCreate(savedInstanceState);
12. setContentView(R.layout.activity_main);
13. tabHost= (FragmentTabHost)
findViewById(android.R.id.tabhost);
14. tabHost.setup(this,
15. getSupportFragmentManager(),android.R.id.tabconte
nt);
16. tabHost.addTab(tabHost.newTabSpec("tab1").setIndicator("
Lengüeta 1"),
17. Tab1.class, null);
18. tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator("
Lengüeta 2"),
19. Tab2.class, null);
20. tabHost.addTab(tabHost.newTabSpec("tab3").setIndicator("
Lengüeta 3"),
21. Tab3.class, null);
22. }
23. }
Observa como la clase creada extiende de FragmentActivity en
lugar de Activity. Esto permitirá que la actividad trabaje
con fragments; en concreto, vamos a crear un fragment para cada
lengüeta. Se han añadido varias líneas en el método onCreate().
Empezamos inicializando la variable tabHost, luego se utiliza el
método setup() para configurarla. Para ello indicamos el contexto,
manejador de fragments y donde se mostrarán los fragments.
Cada una de las siguientes tres líneas introduce una nueva
lengüeta usando el método addTab(). Se indican tres parámetros:
un objeto TabSpec, una clase con el fragment a visualizar en la
lengüeta y un Bundle por si queremos pasar información a la
lengüeta. El método newTabSpec() crea una nueva lengüeta en un
TabHost. Se le pasa como parámetro un String, que se utiliza como
identificador y devuelve el objeto de tipo TabSpec creado.
Nota sobre Java: Dado que el método newTabSpec() devuelve un
objeto de tipo TabSpec, tras la llamada. podemos llamar al
método setIndicator(), que nos permitirá introducir un descriptor en
la pestaña recién creada.
NOTA: También podremos asignar iconos a las lengüetas con el
método setIndicator(). En el capítulo siguiente se estudiarán los
iconos disponibles en el sistema y cómo crear nuevos icono. En las
últimas versiones de Android solo podemos visualizar un texto o un
icono. Para ver el icono introduce un texto vacío.
4. Crea un nuevo layout y llámalo tab1.xml:
1. <LinearLayoutxmlns:android="http://schemas.android.com/apk/
res/android"
2. android:layout_width="match_parent"
3. android:layout_height="match_parent"
4. android:orientation="vertical" >
5. <TextView
6. android:id="@+id/text"
7. android:layout_width="match_parent"
8. android:layout_height="match_parent"
9. android:gravity="center_vertical|center_horizontal"
10. android:text="Lengüeta 1"
11. android:textAppearance="?android:attr/textAppearanceMe
dium" />
12. </LinearLayout>
5. Crea una nueva clase con Tab1.java:
public class Tab1 extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.tab1, container, false);
}
}
Nota sobre Java: Pulsa Alt-Intro en Android Studio o Ctrl-Shift-
O en Eclipse para que automáticamente se añadan los paquetes
que faltan. Si la clase Fragment se encuentra en más de un
paquete, selecciona
android.support.v4.app.FragmentTabHost.
Un fragment se crea de forma muy parecida a una actividad.
También dispone del método onCreate(), aunque en este ejemplo
no se introduce código. Un fragment también tiene asociada una
vista, aunque a diferencia de una actividad, no se asocia en el
método onCreate(), sino que dispone de un método especial para
esta tarea: onCreateView().
6. Repite los dos pasos anteriores para
crear tab2.xml y Tab2.java.
7. Repite de nuevo para crear el layout tab3.xml y la
clase Tab3.java.
8. Modifica estos ficheros para que cada layout sea diferente y
para que cada fragment visualice el layout correspondiente.
9. Ejecuta el proyecto y verifica el resultado.
NOTA: Si en uno de los layouts asignados a un fragment has
utilizado el atributo onClick, el método indicado ha de ser
introducido dentro de la actividad. Si lo introduces dentro del
fragment no será reconocido.