Está en la página 1de 125

Activity entender y usar una

Actividad
Aqu vamos a extendernos para explicar completamente que es una actividad. Si quieres ir
directamente al cdigo est al final. Y si no te sientes interesado por conocer
completamente qu es una actividad ser mejor que mires en otros de los cientos de
tutoriales ms directos que hay por Internet. Empecemos a comprender a fondo que es una
Activity de Android (Actividad en espaol).
Todos sabemos que es una aplicacin informtica. Pero por si lo hemos olvidado lo
resumo: una aplicacin es un programa, que es una herramienta que permite al usuario
realizar algn que otro tipo de trabajo (estos trabajos pueden ser, editar un texto con una
herramienta de edicin de textos, jugar a un juego, usar una calculadora, todo lo que se nos
ocurra). Y una aplicacin internamente consta de cdigo, as como ficheros que pueden ser
de audio, binarios, entre otros. Si, por ejemplo, una aplicacin fuera el Deporte, esta
contendra internamente todos los deportes posibles como gimnasia rtmica, hacer
flexiones, bicicleta, correr, baloncesto, etc. Por cierto, la aplicaciones para dispositivos
mviles se llaman App -viene de convertir en chic y estilosa la palabra en ingls
Application, lo que es quedarnos con las tres primeras letras- es lo mismo con otro
nombre ms modernamente guay.
Entre el cdigo que nos encontramos, en Android, se usa el termino
de Activity (Actividad en espaol) para denominar a un tipo de clases java que heredan
de Activity -no te preocupes si no entendiste esto, lo explicaremos un poco ms adelante.
Una actividad, como su propio nombre indica, es algo que el usuario puede hacer. El smil
que se me ocurre ahora mismo, con el ejemplo anterior, es el de actividad fsica, que es un
conjunto de movimientos del cuerpo que obtienen como resultado un gasto de energa. En
Android una actividad es lo mismo, es un conjunto de acciones (tocar la pantalla para
apretar un botn, para escribir con el teclado, etc) que son una iteracin directa con el
usuario y que afectan a una parte de la aplicacin. Para concretar ms, vamos a suponer que
nuestra actividad fsica es correr -es una parte activa de la aplicacin- con lo que nuestra
actividad ser correr.
Para entenderlo mejor, vamos a suponer que tenemos la App mencionada anteriormente se
llama el Deporte. Esta tiene actividades en su interior que son:
Correr
Baloncesto
Flexiones
Con stas nos vale para ejemplificar lo que queremos, podra haber ms o menos como se
mencion antes.
Lo que queremos hacer es correr, con lo que lanzamos nuestra actividad de correr.
Actividad que estar en primero plano y que contar con un ciclo de vida.
Una actividad se caracteriza por tener un ciclo de vida. Un ciclo de vida, al igual que el
ciclo vida de un animal: nace, crece, come, se reproduce y muere; tambin, es semejante en
una actividad. De la actividad de correr tendra el siguiente ciclo de vida: estiramos antes de
empezar a correr, comenzamos a correr, corremos a tope, en cierto momento decidimos
hacer una pausa para hacer flexiones, luego podemos decidir continuar con la carrera, y en
otro momento dejamos correr para otro da. El siguiente diagrama (modificacin del oficial
para realizar el ejemplo, diagrama oficial que mostramos ms adelante) muestra como se
desarrolla el ciclo de vida de la actividad de correr. chale un vistazo rpido y contina
leyendo la explicacin:

Como habrs visto, el ciclo de vida no es del todo lineal, sino que podemos tomar
decisiones y actuaremos en consecuencia, por ejemplo, podemos decidir hacer un descanso
y luego continuar corriendo o terminar. Pero lo que es lineal es lineal (en el ciclo de vida
animal es lineal comer antes de hacer cacotas, si no se come lo segundo es imposible de
conseguir), siempre calentaremos antes de correr, sino no es un deporte decidir saltarnos
el calentamiento no elimina la linealidad, el calentamiento no se puede hacer mientras se
corre, o se hace antes o no se hace (por evitar dudas con el vocabulario, explicamos que
calentar siempre es antes de realizar un deporte, no despus; para ms dudas consular la
RAE).
Puede que existan preguntas acerca de los dos crculos rojos del diagrama, suelen llevar a
confusin, pero son completamente diferentes (Tambin pueden darse dudas en algunos
estados como el de pausar y parar, pero esos y otros que puedan suscitar dudas se
esclarecern en cuanto veamos un poco ms adelante como funciona ese ciclo de vida en
formato App):
El que mata a la actividad lo hace porque algo ms importante requiere nuestra atencin
absoluta, y no tenemos tiempo para seguir corriendo. No se decide terminar de correr pero
se acaba. Retomaremos la actividad de correr desde el principio cuando queramos.
El que concluye a la actividad es porque decidimos terminar de correr, entonces acabamos
la actividad.
Hemos comentado otras dos actividades: hacer flexiones y baloncesto. En cierto momento
del ciclo de vida de la actividad de correr, podemos decidir hacer la actividad de hacer
flexiones. Con lo que ponemos en segundo plano a la actividad de correr y empezamos con
la de hacer flexiones decir que la actividad de hacer flexiones tambin tiene su propio
ciclo de vida que no dibujaremos por ser innecesario, te lo imaginas . La actividad de
baloncesto tambin tiene su propio ciclo de vida, pero en este ejemplo nunca ser puesto en
marcha simplemente hemos puesto la actividad de baloncesto para ejemplificar que puede
haber actividades que nunca se ejecuten.
Ahora vuelve al grfico anterior e imagnate que has salido a correr, haz un recorrido
mental por el ciclo de vida de la actividad de correr y vers como todo va cobrando sentido.
Cuando acabes mira el siguiente ciclo de vida del mismo diagrama de ejemplo (el diagrama
es una modificacin del oficial que mostramos un poco ms adelante, paciencia), sta vez
suponiendo que es una App de verdad en un Smartphone o Tablet. A la que observamos el
siguiente diagrama, imagnate que tienes instalada la aplicacin El Deporte, y que te
dispones a arrancar la actividad de correr en tu mvil, que la vas a ver en la pantalla, vas a
poder tocar, e interactuar directamente; esta va a ser la actividad activa.

Si pensamos en todo lo que podemos hacer con nuestro mvil teniendo la aplicacin en
marcha, y delante de nosotros la actividad de correr en ejecucin es posiblemente (stas no
son las nicas acciones, otras tambin desencadenarn los mismos caminos por el ciclo de
vida):
Arrancar la actividad: Pasar por Crear, Empezar y Continuar, para llegar a la ejecucin
normal.
Usar de manera normal la actividad: estamos en la actividad en ejecucin.
Una ventana emergente se ha abierto: Pasar por Pausar.
Cambiar a otra actividad o bloquear el mvil: Pasar por Pausar y Parar. (Nota aclaratoria: si
se cambia a otra actividad pasa necesariamente por pausar y parar, no ha tenido que surgir
una ventana emergente para pasar por pausar, si se cambia de actividad se pasa por ambos
estados directamente; esto se da con otras acciones que pasen por varios estados).
Apagar el mvil: Pasar por Pausar, Parar y Destruir.
Entendido esto veamos el ciclo oficial de una actividad (as como los anteriores grficos
son una modificacin ofrecida por www.Jarroba.com para ejemplificar sobre el oficial, el
siguiente grfico es un traduccin del oficial de Android, el diagrama oficial est disponible
en http://developer.android.com/reference/android/app/Activity.html).

Empezamos a hablar en trminos de programacin. Como vemos en los recuadros existen
varios mtodos con nombres en ingls iguales a los que explicamos anteriormente. Estos
mtodos estn en la clase Activity, clase que tendremos que heredar para que nuestra clase
se convierta en una actividad de la siguiente forma (Nota: hasta que no avise de lo
contrario, esto es cdigo no funcional, con lo justo para entender la teora; aviso ms
adelante cuando aparezca el cdigo funcional):
public class Correr extends Activity {
//Aqu estar contenido de toda la actividad de Correr
}
Podemos aadir opcionalmente cada uno de los mtodos para sobrescribirlos (esto lo indica
el @Override) a la clase padre Activity, no siendo obligatorio ninguno. Dentro
escribiremos el cdigo que queramos que se ejecute, y cada mtodo ser llamado por la
clase Activity en el momento indicado anteriormente. A continuacin escribimos todos los
mtodos posibles, los que no necesitemos ni los escribimos. No ponerlos no les priva de
existencia, siguen existiendo en la clase Activity, por tanto en el ciclo de vida de nuestra
Actividad, pero al ejecutarse a su momento estarn vacos.
public class actividad_de_correr extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Nuestro cdigo a ejecutar en este momento
}

@Override
public void onStart(){
super.onStart();
//Nuestro cdigo a ejecutar en este momento
}

@Override
public void onRestart(){
super.onRestart();
//Nuestro cdigo a ejecutar en este momento
}

@Override
public void onResume(){
super.onResume();
//Nuestro cdigo a ejecutar en este momento
}

@Override
public void onPause(){
super.onPause();
//Nuestro cdigo a ejecutar en este momento
}

@Override
public void onStop(){
super.onStop();
//Nuestro cdigo a ejecutar en este momento
}

@Override
public void onDestroy(){
super.onDestroy();
//Nuestro cdigo a ejecutar en este momento
}

}
Para empezar, recomiendo usar nicamente el mtodo onCreate, que es el que se ejecuta al
arrancar la actividad, el resto de mtodos los emplearemos en caso de necesitarlos.
Si te preguntas para que se usa el resto de mtodos, imagnate un juego en nuestro mvil.
Estamos jugando y en cierto momento nos da por apagar el mvil. Para no perder el
progreso, en el onDestroy recolectamos los datos de la partida y los guardamos en la
memoria persistente. As la prxima vez que juguemos, en el onCreate preguntar a la
memoria si existen datos guardados del juego, y cargar la partida en el mismo instante en
la que la dejamos.
public class actividad_de_correr extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Nuestro cdigo a ejecutar en este momento
}

}
A partir de aqu expondremos un ejemplo con cdigo completamente funcional.
Realizaremos la aplicacin El_Deporte. Dentro contendr dos actividades: Correr y
Flexiones (quitamos la de baloncesto por simplificar el cdigo). Creamos un nuevo
proyecto de Android, le ponemos el nombre de la aplicacin El_Deporte y pulsamos todo
el rato a Next hasta terminar, as tener le proyecto listo para trabajar.

Vamos a la carpeta res y ah a la carpeta layout y creamos dos xml.
Uno llamado layout_correr.xml con el siguiente cdigo (como construir y entender este
cdigo xml lo explicaremos en otro tutorial, aqu nos lo creemos):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Estamos corriendo"
android:textAppearance="?android:attr/textAppearanceLarge" />

<Button
android:id="@+id/button_flexiones"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Ponerse a hacer Flexiones"
android:onClick="clicEnBoton_IrAFlexiones"
/>

</LinearLayout>
Este layout muestra al usuario:

Y otro layout_flexiones.xml, con el siguiente cdigo:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Estamos haciendo Flexiones"
android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>
Este otro muestra por pantalla:

Por norma general, una actividad est asociada a un Layout. Un Layout es la ventana o
vista que el usuario ve en la pantalla: botones, textos, barras de desplazamiento, etc. La
asociacin se hace en el onCreate con el mtodo llamado setContentView, como veremos
en el siguiente cdigo.
Si has visto algo del patrn Modelo-Vista-Controlador, decirte que lo que llamamos en
Android Layout es la Vista, la Activity debera de ser el Modelo, y el resto de clases
actuarn de Controlador.
Creamos una nueva actividad que llamamos Correr y ponemos el siguiente cdigo.
package com.example.el_deporte;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class Correr extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_correr);
}

public void clicEnBoton_IrAFlexiones (View view) {
Intent intent = new Intent(this, Flexiones.class);
startActivity(intent);
}

}
Aqu tenemos el onCreate al que se le pasa por parmetro una variable que se llama
savedInstanceState de tipo Bundle. Esto lo explicaremos en otro tutorial ms
extendidamente. Pero para que vayas tomando conceptos un resumen rpido: un Bundle
son datos que le pasamos a esta actividad para inicializar su estado. En este ejemplo no lo
usamos, pero si pensamos por ejemplo en un juego, en el que se pide en una actividad el
sexo del personaje, y pasamos a la siguiente actividad, en el que se ve nuestro personaje
con el sexo elegido; el sexo como variable hombre o mujer ha tenido que ser pasado de
algn modo de una actividad a otra, se hace con Bundle.
El onCreate requiere iniciar al padre antes de todo, de ah la
lnea: super.onCreate(savedInstanceState);
En la lnea siguiente establecemos que Layout queremos asociar a esta actividad, como es
la actividad correr, es justo asociarle el layout layout_correr, se hace como se muestra
en: setContentView(R.layout.layout_correr);
Existe otro mtodo normal y corriente llamado cliclEnBoton_IrAFelxiones que es el que
se ejecuta cuando hacemos clic en el botn con el texto Ponerse a hacer Flexiones. Este
se llama desde el propio xml en la lnea android:onClick=clicEnBoton_IrAFlexiones y lo
que hace es que al pulsar el botn, este mtodo se ejecute.
Este mtodo lo nico que hace es abrir la otra actividad Flexiones. Se hace con algo
llamado Intent. Un Intent es declarar la intencin de lo que se quiere hacer, en este
caso la intencin es ejecutar la actividad Flexiones aunque podra decir que adems de
abrir otra actividad lo que queremos es tambin pasar ciertos datos como en el ejemplo
anterior del juego con el sexo. Dicho de otro modo, un Intent es un paquete con todo lo
que queramos configurar la nueva activity a ejecutar. Solo falta decir que el this es el
contexto de la actividad actual (para saberlo todo sobre el Context mira este artculo). Esto
lo realiza el cdigo: Intent intent = new Intent(this, Flexiones.class);
Despus de declarar la intencin hay que lanzar la actividad con: startActivity(intent);
Para llegar a la siguiente actividad y Layout asociado necesitamos su cdigo. Creamos otra
nueva actividad que llamamos Flexiones con este cdigo:
package com.example.el_deporte;

import android.app.Activity;
import android.os.Bundle;

public class Flexiones extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_flexiones);
}

}
As cuando lleguemos a esta actividad, se mostrar por pantalla el Layout correspondiente.
Pero existe un problema de seguridad que har que la aplicacin falle si intentamos esto sin
ms. Nos queda modificar el fichero llamado AndroidManifest.xml. Este fichero es el
encargado de manejar los permisos de la aplicacin, y aqu hay que declarar todo lo que
nuestra aplicacin pueda suponer un problema de seguridad. En este Manifiesto, tendremos
que poner si nuestra aplicacin har uso de Internet, si va a poder realizar llamadas, etc;
estos son los permisos que el usuario tiene que aceptar cuando el usuario se dispone a
instalar una aplicacin. La apertura de actividades tiene que estar controlado desde este
fichero.
Para ello vamos al AndroidManifest.xml. En la pestaa Application, en el apartado
Application Nodes pulsamos el botn Add.
En la ventana que se nos abre, nos aseguramos que est marcada la casilla Create a new
element at the top level, in Application. Elegimos Activity y pulsamos OK.

Ahora, aseguramos que tenemos seleccionada el nuevo nodo que hemos creado que se
llama Activity. Estarn todos sus campos correspondientes a la derecha en blanco,
pulsamos en Name en el botn Browse.

Otra ventana nueva se nos abrir. Esperamos unos segundos a que carguen todas las
actividades que tenemos un porcentaje nos avisar de ello- y seleccionamos la actividad
que deseamos, en este ejemplo Flexiones. Acabamos pulsando OK.

Guardamos el fichero AndroidManifest.xml y ya est. A continuacin una pantalla de
cmo queda finalmente:

Con lo que hemos hecho en el AndroidManifest.xml lo nico que hemos hecho es aadir
la siguiente lnea a su XML:
<activity android:name="Flexiones"></activity>
Si abrimos el XML del AndroidManifest.xml nos habr quedado una estructura parecida
a la que sigue:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.el_deporte"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />

<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".Correr" android:label="">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="Flexiones"></activity>
</application>

</manifest>
Ya podemos ejecutar nuestra aplicacin en el emulador y probar como hemos hecho una
actividad que al pulsar el botn se pasa a la otra. Como llevamos diciendo en el ejemplo de
correr, estamos corriendo en la siguiente pantalla:

Pulsamos el botn de Ponerse a hacer Flexiones y pausamos la actividad de Correr para
arrancar la actividad de Flexiones.

Para volver a la actividad anterior pulsamos el botn de atrs del dispositivo, con lo que la
actividad de Correr continuar.
Puedes descargarte el proyecto entero desde aqu: Descargar App El_Deporte
Esperamos que te haya esclarecido lo relacionado con todo lo relacionado sobre actividades
de Android, ya que es lo ms gordo que tiene -y ms importante- requiere ser bien
entendido. Para cualquier pregunta o aclaracin en un comentario que responderemos lo
antes posible.
Recomiendo que prosigas con el estudio de Android en el siguiente artculo sobre el
Context pinchando aqu, donde explicamos en profundidad qu es y para qu sirve.

Ver en vivo como funciona el ciclo de vida de una actividad: Para probar como funciona
el ciclo de vida de una actividad, lo mejor es verlo por nosotros mismos. Para ello
sustituimos la actividad Correr por el siguiente cdigo, donde se muestran todos los estados
por los que puede pasar:
package com.example.el_deporte;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.util.Log;

public class Correr extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_correr);
Log.v("test", "Create");
}

public void clicEnBoton_IrAFlexiones (View view) {
Intent intent = new Intent(this, Flexiones.class);
startActivity(intent);
}

@Override
public void onStart(){
super.onStart();
Log.v("test", "Start");
}

@Override
public void onRestart(){
super.onRestart();
Log.v("test", "Restart");
}

@Override
public void onResume(){
super.onResume();
Log.v("test", "Resume");
}

@Override
public void onPause(){
super.onPause();
Log.v("test", "Pause");
}

@Override
public void onStop(){
super.onStop();
Log.v("test", "Stop");
}

@Override
public void onDestroy(){
super.onDestroy();
Log.v("test", "Destroy");
}

}
Hemos aadido a este cdigo un log en cada mtodo del ciclo de vida para poder ver por el
LogCat de Android la salida.
Trastear un poco con esto nos har entender como funciona el ciclo de vida de una
actividad.
Por ejemplo:
1 Supongamos que arrancamos la aplicacin, se cargar la actividad de Correr, y por el
LogCat se nos mostrar en cada lnea: Create, Start y Resume.
2 Ahora pulsamos el botn, como otra actividad se nos pone encima ocultndola
completamente, se mostrar en este orden: Pause y Stop.
3 Si pulsamos el botn de volver, retomamos la actividad de Correr y se mostrar: Restart,
Start y Resume.
4 Si pulsamos el botn de inicio para volver al escritorio, se nos mostrar: Pause y Stop.
Podemos hacer todas las pruebas que queramos, para entender perfectamente el ciclo de
vida de la actividad. Es recomendable que eches un vistazo al diagrama para poder seguir la
vida de una actividad.
Fragments (fragmentos) en Android
Este artculo es tan profundo e ilustrativo que bien podramos haber titulado como
Fragment vs Activity, Aplicaciones soportadas para varios tamaos de pantalla,
Aprende a desarrollar en Android para APPs multi-dispositivo o incluso Fragments fcil
o para Dummies. Antes de empezar he de decir que requiere conocimientos de Android
avanzados. Previa a la descripcin, te recomiendo que eches un vistazo a las Activitys
en http://jarroba.com/activity-entender-y-usar-una-actividad/. Para los ejemplo usaremos
listados, que detallamos en http://jarroba.com/listview-o-listado-en-android/, por lo que te
recomiendo que le eches un vistazo si no lo has hecho ya. Empezaremos con unos
conceptos mnimos pero breves, y programaremos nuestro primero programa funcional con
Fragments en Android.

Me entusiasmo la frase que una vez dijera el filsofo Confucio (extrada
de http://es.wikiquote.org/wiki/Confucio):
Cada cosa tiene su belleza, pero no todos pueden verla
Si la extrapolamos al terreno tecnolgico en el que nos movemos, al de las pantallas
tctiles; descubriremos que no es lo mismo un mvil, que una Tablet, que un reloj, que un
monitor de unas pocas pulgadas, a una gran televisin, etc. Todas estas cosas tienen
pantallas de muy diferente tamao y cada uno es bello por lo que es. No podemos
resistirnos al ver la belleza de los tamaos de las pantallas, pues no todos los usuarios
debern de ver lo mismo si usan objetos con tamaos de pantalla diferentes. Como
desarrolladores tenemos que ver la belleza completa de cada cosa. Y tiene una razn de ser.

Como desarrollador de Android es muy comn estar acostumbrados a programar las views
aplicando dp para los tamaos, as las vistas se escalan para cada tipo de pantalla. Est bien
para pantallas de pulgadas aproximadas a la que hemos desarrollado la aplicacin en una
primera instancia. Pero para nada est bien en pantallas de una gran diferencia de pulgadas.
Como es disear una APP para un televisor de 100 pulgadas, y que tambin funcione en un
reloj de 2 pulgadas; evidentemente se iba a ver diminuto e inmanejable. Lo mismo ocurre
con la forma, no es lo mismo un Smartphone que tiende a ser rectangular bastante alargado,
a un Tablet que suele respetar las proporciones ureas (misma forma que una tarjeta de
crdito). Debemos hacernos siempre del mejor aprovechamiento del espacio de cada
pantalla tanto en tamao como en forma- siempre en virtud de la comodidad del usuario.
Nota: Aqu solo nos interesa -adems de la forma de la pantalla- el tamao de pantalla,
hablamos en pulgadas (normalmente la vemos representada como 7 o 7 pulgadas), a ms
pulgadas entonces pantalla ms grande, a menos ms pequea. No nos interesa, y no
confundir con el tamao, la resolucin de la pantalla (que solemos ver cmo 1024768).
Y porque no nos interesa? Porque la pantalla es a su vez interfaz tctil, por lo que define la
comodidad de uso. Una pantalla ms grande se ver ms contenido que en ms pequea con
el mismo esfuerzo; adems, una pantalla ms grande tiene ms espacio para pulsar y
manejar que una ms pequea. De ah que la resolucin carezca de importancia.
Para entenderlo vamos a suponer el siguiente ejemplo. Queremos un listado de animales.
En cada fila de la lista mostrar el nombre del animal y una foto en miniatura.

Al seleccionar un animal (una fila de la lista), me muestre el animal en detalle, es decir la
descripcin del animal.

Si te fijas en las imgenes anteriores, vemos el enunciado del ejemplo perfectamente
reflejado en estas imgenes. Pero fjate en una cosa ms, Qu dispositivo es el que ejecuta
la aplicacin? Un Smartphone, propiamente. Es decir, un dispositivo que cabe en la mano y
que ir de las 3 a las 5 pulgadas ms o menos; adems, su forma suele ser rectangular
alargada. Ahora bien, imagnate las mismas dos imgenes anteriores en un Tablet de unas 7
a 10 pulgadas aproximadamente. Si usramos la aplicacin directamente sobre un Tablet, te
muestro como quedara el listado:

Horrible No crees que es una prdida de espacio de la pantalla impresionante? Que la
parte de la derecha pudiera dar lugar a mostrar otra cosa al usuario. Teniendo tanta pantalla
se debe de aprovechar. Esto ltimo se escusa en proporcionar una mejor experiencia al
usuario con pantallas de tamaos diferentes, as como la de proporcionar acciones que de
no disponer de cierto tamao de pantalla no se podran llevar a cabo, adems de evitar la
fragmentacin de nuestro programa (seguro que te suena lo de la fragmentacin de
Android, pues en un programa Android se corrige con el uso de fragmentos, as nuestra
aplicacin ser universal y usable para cualquier tamao de pantalla).
Con el ejemplo, para una Tablet, se me ocurre que podramos aprovechar el espacio
derecho para mostrar el detalle. As es mucho ms cmodo y no hay que estar volviendo
atrs cada vez.

Mucho mejor. Al seleccionar un elemento del listado, se mostrar a la derecha el detalle del
mismo. Mejor aprovechamiento de la pantalla y mucho ms cmodo (no hay que volver
atrs, se puede seleccionar otro inmediatamente).
Cabe aclarar que si mantenemos este diseo para un Smartphone, la comodidad del Tablet
se pierde, pues no se podra leer bien la descripcin del pjaro al aparecer muy pequea y el
listado sera difcil de pulsar al ser muy estrecho. Por esto tiene sentido que en el mvil
tenga un diseo y funcionalidades diferentes al del Tablet.
Por cuestiones de espacio nos limitaremos al ejemplo de Smartphone y Tablet. Pero
imagina que queremos hacer esta misma aplicacin para un reloj de unas 2 pulgadas, puede
que en vez de poner un listado pusiramos un grid con las imgenes de los pjaros para que
el dedo pudiera pulsar mejor los elementos, y la descripcin aparecera aparte sin foto. O en
una televisin de 40 pulgadas imagina la cantidad de cosas que entraran; podramos, por
ejemplo, poner al lado de la descripcin un vdeo del pjaro que vuela y debajo la ficha
tcnica, todo en la misma pantalla. Esto quiere decir que nos ajustamos al tamao para
realizar el diseo y la funcionalidad.
Por suerte para nosotros, no tenemos que hacer un diseo para cada pulgada de cada
pantalla y para cada forma. Nos atendemos a la limitacin por las modas. Pongo todos los
dispositivos existentes con Android que pudiera ser bueno prestar atencin al diseo y a la
funcionalidad. Siempre claro, dependiendo del alcance de nuestra aplicacin (las pulgadas
y formas son orientativas):
Reloj (1 a 2 pulgadas, cuadrado)
Smarphone o dispositivo GPS (3 a 5 pulgadas, rectangular alargado)
Phablet (5 a 7 pulgadas, rectangular alargado)
Tablet (7 a 12 pulgadas, proporcin aurea)
Pantalla de un ordenador (14 a 30 pulgadas, rectangular alargado o proporcin aurea)
Televisin (30 a 80 pulgadas, proporcin aurea)
Proyector (80 a 300 pulgadas, proporcin aurea)
Depender del desarrollador saber a qu diseos y que funcionalidades atender en cada
momento.
Y se puede hacer esto en la misma aplicacin? o Se desarrolla una App para cada tamao
de pantalla? La respuesta es, siempre desde la perspectiva del buen programador, se debe
y se puede hacer en la misma aplicacin. Los motivos son muy simples, que seguro ests
harto de escuchar: modularidad y reusabilidad. Esto se logra con los Fragments o
Fragmentos.
Si conoces el comportamiento de las Activities (ver en http://jarroba.com/activity-entender-
y-usar-una-actividad/), advertirs que tienen un ciclo de vida y estn asociadas a una vista
(Layout en XML).
Un Fragment es un trozo (o un fragmento, si apelamos al mismo nombre que lo viste) de
una actividad. Un Fragment tiene su propio Layout y su propio ciclo de vida.
Puedes apreciar, que programndolo una vez, puedes rehusar el cdigo para que se adapte a
diferentes tamaos de pantalla con la disposicin de los elementos que quieras.
Por lo que adivinars que un Fragment siempre ha de estar en una Activity, no puede existir
independiente. Y el ciclo de vida de la Activity contenedora afectar al del Fragment; por
ejemplo, si se pausa la Activity el o los Fragments, que estn en esta actividad, sern
pausados.
Hablando del ciclo de vida de un Fragment, no podemos continuar sin dedicarle la parte
que se merece. Es el siguiente, y no te asustes de lo largo que es, si entendiste el de Activity
este es parecido (Grficos extrados
de http://developer.android.com/guide/components/fragments.html, modificados y
traducidos por www.Jarroba.com):

Para que conozcas a grandes rasgos que es lo que hace cada una de los mtodos, te los
detallo en la siguiente imagen (Referencia
en http://developer.android.com/reference/android/app/Fragment.html):

Nota: Como ya hicieramos con Activity en este otro artculo, dejo un ejemplo simple -sirve
como plantilla o snippet- de un Fragment, con todos sus mtodos (decir tiene que no todos
son obligatorios; pero el constructor vaco s que lo es, lo explico en el siguiente artculo) y
el log puesto para ver por donde va entrando:
public class Fragment_de_ejemplo extends Fragment {

private final String LOG_TAG = "test";

public Fragment_de_ejemplo() {
}

@Override
public void onAttach (Activity activity) {
super.onAttach(activity);
Log.v(LOG_TAG, "onAttach");
}

@Override
public void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v(LOG_TAG, "onCreate");
}

@Override
public View onCreateView (LayoutInflater inflater, ViewGroup
container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.miLayout,
container, false);
Log.v(LOG_TAG, "onCreateView");
/* Aqu podemos seleccionar las Views contenidas en el
Layout para trabajar con ellas, por ejemplo con:
* TipoView miView = (TipoView)
rootView.findViewById(R.id.miViewXML);
*/
return rootView;
}

@Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.v(LOG_TAG, "onActivityCreated");
}

@Override
public void onViewStateRestored (Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
Log.v(LOG_TAG, "onViewStateRestored");
}

@Override
public void onStart () {
super.onStart();
Log.v(LOG_TAG, "onStart");
}

@Override
public void onResume () {
super.onResume();
Log.v(LOG_TAG, "onResume");
}

@Override
public void onPause () {
super.onPause();
Log.v(LOG_TAG, "onPause");
}

@Override
public void onStop () {
super.onStop();
Log.v(LOG_TAG, "onStop");
}

@Override
public void onDestroyView () {
super.onDestroyView();
Log.v(LOG_TAG, "onDestroyView");
}

@Override
public void onDestroy () {
super.onDestroy();
Log.v(LOG_TAG, "onDestroy");
}

@Override
public void onDetach () {
super.onDetach();
Log.v(LOG_TAG, "onDetach");
}

}

Hemos credo conveniente dividir este artculo en dos partes por comodidad y
optimizacin. Este primero ms terico, y una segunda parte que dispone de un ejemplo
completo de como programar con Fragments para Android completamente explicado: en
la siguiente pgina, a la que puedes ir pinchando aqu mismo.

Entradas Relacionadas
Error Android Certificado de depuracin caducado

Error Android El emulador se desconecta y no lanza la aplicacin

Preparar las herramientas necesarias para programar en Android

Multitarea en Android


Programar Fragments (fragmentos) en
Android
Despus del primer artculo (ver primera parte aqu), continuamos donde lo dejamos y
preparados para programar. Comenzar con una descripcin ilustrada para que no quepan
dudas, o al menos sean mnimas. Continuemos donde lo dejamos.
Retomamos el ejemplo para disear el Smartphone. Veamos que tendremos una Activity
con un listado que representaremos el diseo como:

Distinguir lo verde como Fragment y lo rojo como Activity. El resto de contenido
pertenece al Layout (texto, imgenes, etc).
Y un al pulsar sobre un elemento de la lista, nos abrir una segunda Activity que ser el
detalle de la entrada:

Ahora un par de preguntas sobre la representacin del detalle de la entrada (la imagen
anterior), para ver si has entendido la teora Cuntos Layouts, es decir, ficheros XML de la
carpeta Layout, componen esta Activity? Y dnde estaran ubicados? La solucin es 2
Layouts, y estn ubicados donde se muestra en la imagen a continuacin (la letra ms
pequea en negrita con rectngulo transparente):

Si no has acertado, no te preocupes, a continuacin lo explico. Si has dado con la solucin a
la primera, me quito el sombrero, ya que has entendido la complejidad de las vistas de los
Fragments.
La Activity tiene asociado un Layout como siempre, que llamaremos
Layout_activity_detalle (engloba todo el rectngulo rojo) es la asociacin Layout con
Activity tpica. Y hemos dicho que el Fragment es como si fuera una Activity pero
pequea, con lo que tambin tiene asociado un Layout que llamamos
Layout_fragment_detalle. Espero que los nombres sean acertados y aclaratorios
Hemos dejado para el final el primero, porque tiene una particularidad. Si te hago las dos
preguntas anteriores Dnde y cuntos Layouts componen el listado? Podras decirme que
3, pero no son 3 sino 2. Fjate en la siguiente imagen un segundo y te lo explico.

La actividad tiene, como acostumbra, su Layout asociado llamado
Layout_activity_principal_listado. El Fragment no tiene fichero de Layout asociado No
me acabas de decir que s tena Layout, adems, es el fichero XML tiene un ListView
claramente? En Fragments el listado es un caso especial. Si has tocado listas un poco ms
en profundidad sabrs que si extendemos la clase, en vez de con Activity con ListActivity,
no hace falta declarar un fichero con el ListView. Con Fragments es igual si extendemos de
ListFragment. Usaremos este modo por simplificar cdigo. Y aclarar que en este Fragment
existir existe el Layout con el ListView, pero no lo haremos nosotros directamente. Ya
terminamos con el ltimo Layout, el de cada elemento de la lista llamado
Layout_elemento_listado.
Aqu acaba el diseo para dispositivos mviles.
Ahora el de la Tablet en el que me explayar menos en detalles, pasando a lo importante.
Recordamos que queremos que todo se muestra a la vez (listado y detalle).

Notars cmo estn separados los dos Fragments y que solo necesitamos una Activity.
Tambin te hago las mismas preguntas anteriores sobre los Layouts Cuntos y dnde estn
ubicados? Esta es fcil habindolo visto anteriormente.

Bueno, exista una trampa al tratarse de una sola Activity. En el diseo de mvil cada
actividad tena un Layout que contena un Fragment. En el diseo para Tablets, solo existe
una Activity que tiene asociado un Layout que contiene a los dos Fragments. Es razonable
que sea as; quera dejar clara esta diferencia.
Por cierto, estos van a ser todos los Layouts que vamos a utilizar y ninguno ms (todos los
has visto en las imgenes anteriores):

Ya llega el cdigo, tranquilo. Es importante no perderse con tanto archivo y tener las ideas
muy claras.
Previo a revelarte el cdigo XML, hay un simplismo que debes conocer. Se suele pasar por
alto y no debera, es fuente de muchos errores, por consiguiente se obtiene desesperacin al
tratar con Fragments (ya nunca ms ). El tema de Fragments estticos o finales y
dinmicos:
Un Fragment esttico o final es aquel que se declara en el fichero XML de la carpeta
Layout directamente. Este Fragment tendr la cualidad de no ser eliminado o
sustituido por nada -De lo contrario tendremos errores.
Un Fragment dinmico es el que se crea desde cdigo Java y se asocia a un
ViewGroup (Se recomienda el uso de FrameLayout). ste s que se podr eliminar o
sustituir por otro Fragment u otro contenido.
Para entenderlo bien, con el ejemplo del Tablet nos bastar.

Tenemos el listado, que es algo que siempre va a ser igual (podrn aumentar o disminuir los
elementos contenidos en el listado, pero siempre ser un listado), por lo que podemos
declarar su fragment en el XML, es esttico. Y luego tenemos la parte derecha del detalle,
dependiendo del seleccionado en el listado mostrar el detalle de un pjaro (descripcin,
nombre y foto) diferente. Con lo que cada detalle de cada pjaro tendr su propio Fragment
-si los equiparamos a las hojas de un libro, pasar cada Fragment equivaldra a pasar las
hojas del libro de pjaros- por lo que nos interesa que estos Fragments sean dinmicos. Lo
que nos dibujar el siguiente Layout con un Fragment esttico en XML y un FrameLayout
que contendr a los Fragments dinmicos.

Por lo que el cdigo de layout_activity_principal_dospaneles.xml ser:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:baselineAligned="false"
android:divider="?android:attr/dividerHorizontal"
android:orientation="horizontal"
android:showDividers="middle" >

<!--
Este fragmento esttico contiene al listado
-->
<fragment
android:id="@+id/fragment_listado"
android:name="jarroba.invarato.fragmentos.Fragment_Lista"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>

<!--
Este FrameLayout contendr un fragmento dinmico con el contenido
del elemento pulsado del listado
-->
<FrameLayout
android:id="@+id/framelayout_contenedor_detalle"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />

</LinearLayout>
Del mismo modo, para mvil, tenemos por separado el listado con el Fragment esttico.
Cuyo cdigo de layout_activity_principal_listado.xml es:
<!--
Este fragmento esttico contiene al listado
-->
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_listado"
android:name="jarroba.invarato.fragmentos.Fragment_Lista"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" />
Y por otra parte, de manera separada pero con la misma lgica al que hemos explicado de
la Tablet, tenemos el Fragment dinmico para el detalle. Paralayout_activity_detalle.xml:
<!--
Este FrameLayout contendr un fragmento dinmico con el contenido del
elemento pulsado del listado
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android
"
android:id="@+id/framelayout_contenedor_detalle"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Tambin tenemos la estructura simple de la vista de cada elemento del listado
en layout_elemento_listado.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center|left"
android:orientation="horizontal" >

<ImageView
android:id="@+id/imageView_imagen_miniatura"
android:layout_width="80dp"
android:layout_height="80dp"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:contentDescription="Descripcin del contenido de la
imagen"
android:src="@android:drawable/ic_menu_gallery" />

<TextView
android:id="@+id/textView_titulo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>
Y el del detalle, en layout_fragment_detalle.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center|top"
android:orientation="vertical" >

<TextView
android:id="@+id/textView_superior"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />

<ImageView
android:id="@+id/imageView_imagen"
android:layout_width="178dp"
android:layout_height="178dp"
android:adjustViewBounds="true"
android:contentDescription="Descripcin del contenido de la
imagen"
android:scaleType="fitXY"
android:src="@android:drawable/ic_menu_gallery" />

<TextView
android:id="@+id/textView_inferior"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Small Text"
android:textAppearance="?android:attr/textAppearanceSmall" />

</LinearLayout>
Ya tenemos las vistas. Antes de entrar con Java, tenemos que hacer una diferenciacin ms.
Necesitamos diferenciar con qu tipo de pantalla estamos tratando para poder aplicar el
diseo de mvil o de tablet. Esta diferenciacin Android la hace muy bien gracias a las
carpetas values, que estn en la carpeta res.

Tendremos 3 carpetas values (ms informacin
en http://developer.android.com/guide/practices/screens_support.html#DeclaringTabletLay
outs):
values-large: para pantallas grandes; es decir, para Tablets (Necesario para que
funcione en la versin 3 de Android). Crearemos en esta carpeta un nuevo fichero
XML llamado layout.xml (lo explico un poco ms adelante).
values-sw600dp: para pantallas con un ancho mayor a 600dp (independientemente de
la rotacin de la pantalla); para Tablets de este tamao o ms. Este valor lo podemos
cambiar, pero 600 nos va a funcionar muy bien para nuestros propsitos. Crearemos
en esta carpeta otro nuevo fichero XML tambin llamado layout.xml (lo explico un
poco ms adelante).
values: carpeta de valores para el resto de dispositivos que no cumplan las condiciones
anteriores. Lo usaran los Smartphones, o las Tablets pequeas que no cumplan el
tamao mnimo que hemos puesto. No tocamos ni aadimos nada en esta carpeta.
Hemos creado dos ficheros llamados layout.xml. Ambos contendrn el mismo contenido
que es el siguiente:
<resources>
<item name="layout_activity_principal_listado"
type="layout">@layout/layout_activity_principal_dospaneles</item>
</resources>
Esto es un truquito que te cuento para no repetir ficheros: los alias. Podramos haber creado
varias carpetas layout pero tendramos cdigo duplicado con lo mismo; con el alias
evitamos repetir cdigo innecesariamente. Este alias lo nico que hace es sustituir el
contenido de un XML por otro. As, si la pantalla es pequea cargar directamente el
XML layout_activity_principal_listado.xml en el que solo se muestra un listado; y si es
grande, el contenido de este fichero ser sustituido por el contenido del fichero
layout_acitivity_principal_dospaneles.xml que dispone un Fragment a la izquierda para
el listado y un FrameLayout a la derecha para el Fragment dinmico del detalle. Para mayor
claridad, echa un vistazo a la imagen siguiente:

Ahora ya podemos meternos de lleno con el cdigo Java. Primero te voy a mostrar la
estructura completa del proyecto, debers crear las clases Java (que detallo a continuacin)
y aadir las imgenes. De la carpeta res ya est todo terminado. De la siguiente imagen
solo hemos creado lo que est en rojo para hacer la aplicacin.

Empecemos por el cdigo primero en ejecutarse, que es Activity_Principal.java. Esta es
una Activity, pero para tratar con Fragments necesitamos un tipo de Activity especial
llamada FragmentActivity de la que extenderemos la clase. Pero antes vamos a explicar
en esencia lo que hace, que son dos cosas y luego muestro el cdigo:
Diferenciar la cantidad de elementos que maneja para cada tipo de dispositivo: En el
onCreate le asociaremos el Layout layout_activity_principal_listado.xml
recordemos que su contenido tendr nicamente un listado, o un listado y un detalle,
dependiendo del tamao de la pantalla. Para saber si estamos trabajando con dos
Fragments en la misma Acitivity, es tan sencillo como preguntar si existe el detalle,
sino existe estaremos trabajando con un solo Fragment que ser sin lugar a dudas el
listado.
Comunicar a los Fragments: Programaremos los Fragments de manera completamente
modular; es decir, un Fragment no se comunica con otro directamente sino a travs de
interfaces. Funciona del siguiente modo (para mayor claridad, echar un vistazo a la
imagen inferior que es para el caso del Tablet; para el Smartphone sera igual, pero
pasndole el dato de una Activity a la otra, y sta ya se lo comunicara al Fragment
con el detalle):

1) Se pulsa sobre un elemento del Fragment que contiene al listado. A travs de un
mtodo de Callback onEntradaSelecionada (esto es programacin por eventos, en este
artculo explicamos su comportamiento, pero resumimos al explicar el cdigo por no ser el
tema principal del artculo) comunica el id de la entrada seleccionada a la Activity que lo
engloba (de ah que implemente a Fragment_Lista.Callbacks).
2) La Activity recoge el dato. Si:
Es Tablet: crea un nuevo Fragment con el detalle, le enva el id para que cargue el
contenido apropiado y lo coloca en el FrameLayout, remplazando cualquier otro
Fragment con el detalle que pueda existir.
Es Smartphone: Crea una nueva Activity al que le enva el id. La nueva Activity
cargar el Fragment con el detalle sobre s misma.
3) Se muestra el Fragment con el detalle al usuario.
Y este es el cdigo correspondiente de esta clase:
public class Activity_Principal extends FragmentActivity implements
Fragment_Lista.Callbacks {

private boolean dosFragmentos;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.layout_activity_principal_listado);

if (findViewById(R.id.framelayout_contenedor_detalle)
!= null) {
dosFragmentos = true;
}
}

@Override
public void onEntradaSelecionada(String id) {
if (dosFragmentos) {
Bundle arguments = new Bundle();

arguments.putString(Fragment_Detalle.ARG_ID_ENTRADA_SELECIONAD
A, id);
Fragment_Detalle fragment = new
Fragment_Detalle();
fragment.setArguments(arguments);

getSupportFragmentManager().beginTransaction().replace(R.id.fr
amelayout_contenedor_detalle, fragment).commit();

} else {
Intent detailIntent = new Intent(this,
Activity_Detalle.class);

detailIntent.putExtra(Fragment_Detalle.ARG_ID_ENTRADA_SELECION
ADA, id);
startActivity(detailIntent);
}
}
}
Comencemos con un Fragment normal, que es el del detalle. Para ello escribimos el cdigo
de Fragment_Detalle.java. Por ser un Fragment normal y corriente extender de
Fragment. Explico el contenido de los mtodos:
Contructor: en los Fragments siempre vaci para poder instanciarlo.
onCreate: recoge el contenido de la entrada.
onCreateView: aqu se maneja la vista, es decir crea y se asocia con el Layout (en
Activity se hace en el onCreate con el mtodo setContentView; pero esto es un
Fragment, funciona de manera diferente y es as como se hace, con inflate(). Averigua
todo sobre inflate() en este otro artculo).
public class Fragment_Detalle extends Fragment {

public static final String ARG_ID_ENTRADA_SELECIONADA =
"item_id";
private Lista_contenido.Lista_entrada mItem;

public Fragment_Detalle() {
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

if
(getArguments().containsKey(ARG_ID_ENTRADA_SELECIONADA)) {
//Cargamos el contenido de la entrada con cierto
ID seleccionado en la lista. Se recomiendo usar un Loader para cargar
el contenido
mItem =
Lista_contenido.ENTRADAS_LISTA_HASHMAP.get(getArguments().getString(AR
G_ID_ENTRADA_SELECIONADA));
}
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container, Bundle savedInstanceState) {
View rootView =
inflater.inflate(R.layout.layout_fragment_detalle, container, false);

//Mostramos el contenido al usuario
if (mItem != null) {
((TextView)
rootView.findViewById(R.id.textView_superior)).setText(mItem.textoEnci
ma);
((TextView)
rootView.findViewById(R.id.textView_inferior)).setText(mItem.textoDeba
jo);
((ImageView)
rootView.findViewById(R.id.imageView_imagen)).setImageResource(mItem.i
dImagen);
}

return rootView;
}
}
Exporto android.support.v4.app o android.app?
A la hora de exportar la librera de Fragment (por ejemplo, aunque tambin podra darse el
caso con FragmentManager, FragmentTransaction, etc). Eclipse te dar a elegir entre las
dos opciones dos: android.app.Fragment -solo funciona a partir de Android 3.0 nivel
11- o android.support.v4.app.Fragment -para cualquier versin de Android.
Nuestra recomendacin es que uses android.support.v4.app.*.
Nunca mezcles en el mismo proyecto las dos libreras a importar (por ejemplo, que hayas
importado android.support.v4.app.FragmentManager y android.app.Fragment ), pues lo
ms probable es que te encuentres con alguna variante del siguiente error en tiempo de
ejecucin:
The method replace() in the type FragmentTransaction is not applicable for the
arguments ()
La solucin ya sabes que debes hacer: buscar y cambiar el archivo importado que no
cumple lo anterior descrito y cambiarlo por el otro (en el anterior ejemplo, nos damos
cuenta y lo cambiamos a android.support.v4.app.FragmentManager
y android.support.v4.app.Fragment ).
Entendido el Fragment normal, ahora uno especial. Implementaremos el del listado
en Fragment_Lista.java. Esta clase es un Fragment, pero es un Fragment especial que
extender de ListFragment, que es el listado preparado para ser Fragment (Aqu no
asociamos ningn Layout, pues al extender de ListFragment ya lo trae puesto). Callaback:
Tendr implementado el Callback que notifique a la Activity de que elemento del listado se
haya pulsado. Explico uno a uno los mtodos aqu usados:
Constructor: Seguro que te fijars en el constructor vaco, es necesario para el correcto
funcionamiento de los Fragments, as que ni se te ocurra quitarlo :D.
onCreate: como ya hicimos en el artculo de listado asignamos el contenido de cada
entrada a cada elemento del listado.
onAttach: Simplemente asegura que el desarrollador haya implementado el Callback,
en la clase que use a este Fragment.
onDetach: Limpia el Callback.
onListItemClick: al extender de ListFragment, es necesario sobrescribir esta clase, que
es la que escucha la pulsacin sobre un elemento de la lista. Y as usaremos el
Callback para notificar a la Actividad del id pulsado.
public class Fragment_Lista extends ListFragment {

private Callbacks mCallbacks = CallbacksVacios;

public interface Callbacks {
public void onEntradaSelecionada(String id);
}

private static Callbacks CallbacksVacios = new Callbacks() {
@Override
public void onEntradaSelecionada(String id) {
}
};

public Fragment_Lista() {
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setListAdapter(new Lista_adaptador(getActivity(),
R.layout.layout_elemento_listado, Lista_contenido.ENTRADAS_LISTA){
@Override
public void onEntrada(Object entrada, View view)
{
if (entrada != null) {
TextView texto_superior_entrada =
(TextView) view.findViewById(R.id.textView_titulo);
if (texto_superior_entrada != null)

texto_superior_entrada.setText(((Lista_contenido.Lista_entrada
) entrada).textoEncima);

ImageView imagen_entrada = (ImageView)
view.findViewById(R.id.imageView_imagen_miniatura);
if (imagen_entrada != null)

imagen_entrada.setImageResource(((Lista_contenido.Lista_entrad
a) entrada).idImagen);
}
}
});

}

@Override
public void onAttach(Activity activity) {
super.onAttach(activity);

if (!(activity instanceof Callbacks)) {
throw new IllegalStateException("Error: La
actividad debe implementar el callback del fragmento");
}

mCallbacks = (Callbacks) activity;
}

@Override
public void onDetach() {
super.onDetach();
mCallbacks = CallbacksVacios;
}

@Override
public void onListItemClick(ListView listView, View view, int
posicion, long id) {
super.onListItemClick(listView, view, posicion, id); mCallbacks.onEntradaSelecionada(Lista_contenido.ENTRADAS_LISTA.get(posicion).id);
}

}
Hasta aqu ya tenemos lo que hace funcionar la estructura de los Tablets.
Continuemos para el caso de Smartphone. Necesitamos un segundo Activity para contener
al Fragment del detalle. Llamaremos Activity_Detalle. Recuerdas que heredaba? A
Activity no, estamos trabajando con Fragments, extiende de FragmentActivity. Solo tiene
un mtodo onCreate que comprobar si ya ha creado al Fragment del detalle para cargarlo,
o no para crearlo. La creacin del Fragment del detalle es igual que en el caso de
Activity_Principal.java.
public class Activity_Detalle extends FragmentActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_activity_detalle);

// Comprobamos que previamente no hayamos entrado en
esta actividad (por ejemplo, al rotar el dispositivo). Si es as se
aade el fragmento al contenedor
if (savedInstanceState == null) {
// Crea el fragmento del detalle de la entrada y
lo aade a la actividad
Bundle arguments = new Bundle();

arguments.putString(Fragment_Detalle.ARG_ID_ENTRADA_SELECIONAD
A,
getIntent().getStringExtra(Fragment_Detalle.ARG_ID_ENTRADA_SELECIONADA
));
Fragment_Detalle fragment = new
Fragment_Detalle();
fragment.setArguments(arguments);

getSupportFragmentManager().beginTransaction().add(R.id.framel
ayout_contenedor_detalle, fragment).commit();
}
}

}
Ya solo nos queda comentar Lista_adaptador.java que encontrars en el artculo del
listado.
Y Lista_contenido.java, que contiene a la clase Lista_entrada del artculo del listado. Lo
hemos hecho as por simplificar el cdigo. Ya que si los datos no van a cambiar, as es muy
fcil hacer una estructura esttica que de elementos que siempre est visible por todas las
clases sea el momento que sea de la ejecucin. Simplemente guardamos unos listados con
el contenido de las entradas estticamente, esto se hace al inicio de la aplicacin.
public class Lista_contenido {

/**
* Donde se guardan las entradas de la lista.
*/
public static ArrayList<Lista_entrada> ENTRADAS_LISTA = new
ArrayList<Lista_entrada>();

/**
* Donde se asigna el identificador a cada entrada de la lista
*/
public static Map<String, Lista_entrada>
ENTRADAS_LISTA_HASHMAP = new HashMap<String, Lista_entrada>();

/**
* Creamos estticamente las entradas
*/
static {
aniadirEntrada(new Lista_entrada("0",
R.drawable.im_buho, "BUHO", "Bho es el nombre comn..."));
aniadirEntrada(new Lista_entrada("1",
R.drawable.im_colibri, "COLIBR", "Los troquilinos (Trochilinae)
son..."));
aniadirEntrada(new Lista_entrada("2",
R.drawable.im_cuervo, "CUERVO", "El cuervo comn (Corvus corax) es
..."));
aniadirEntrada(new Lista_entrada("3",
R.drawable.im_flamenco, "FLAMENCO", "Los fenicopteriformes..."));
aniadirEntrada(new Lista_entrada("4",
R.drawable.im_kiwi, "KIWI", "Los kiwis (Apterix, gr. 'sin alas')
son..."));
aniadirEntrada(new Lista_entrada("5",
R.drawable.im_loro, "LORO", "Las Psitcidas (Psittacidae) son..."));
aniadirEntrada(new Lista_entrada("6",
R.drawable.im_pavo, "PAVO", "Pavo es un gnero de aves..."));
}

/** Aade una entrada a la lista
* @param entrada Elemento que aadimos a la lista
*/
private static void aniadirEntrada(Lista_entrada entrada) {
ENTRADAS_LISTA.add(entrada);
ENTRADAS_LISTA_HASHMAP.put(entrada.id, entrada);
}

/**
* Representa una entrada del contenido de la lista
*/
public static class Lista_entrada {
public String id;
public int idImagen;
public String textoEncima;
public String textoDebajo;

public Lista_entrada (String id, int idImagen, String
textoEncima, String textoDebajo) {
this.id = id;
this.idImagen = idImagen;
this.textoEncima = textoEncima;
this.textoDebajo = textoDebajo;
}
}

}
Y nos falta aadir al AndroidManifest.xml la Actividad que no es la principal, es decir
Activity_Detalle. Este es mi AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="jarroba.invarato.fragmentos"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="18" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity

android:name="jarroba.invarato.fragmentos.Activity_Principal"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity

android:name="jarroba.invarato.fragmentos.Activity_Detalle"
android:label="@string/titulo_detalle_entrada"
android:parentActivityName=".Activity_Principal" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".Activity_Detalle" />
</activity>
</application>

</manifest>
Dejo aqu el cdigo funcional para descargar, bastante comentado para aclarar todava ms
las posibles dudas que queden en el tintero. Descrgalo aqu: Fragmentos
Te recomiendo que lo pruebes tanto con un emulador o dispositivo fsico- de Smartphone,
como de Tablet, para que veas como queda en cada dispositivo.
Nota: si quieres ahorrarte un montn de cdigo aprovechando ahora que entiendes la
arquitectura de los Fragments. Al crear un nuevo proyecto Android puedes seleccionar
Master/Detail Flow en la pgina Create Activity. Lo nico que, como usa ActionBar,
requiere de mnimo Android 3.0 (API 11 o Honeycomb).

Y con esto acabamos los fragmentos. La estructura mental de Fragment tiene cosas que ver
y cosas que son completamente diferentes a la de Activity. Una vez entendidas te aseguro
que son muy fciles


Mucho mejor. Al seleccionar un elemento del listado, se mostrar a la derecha el detalle del
mismo. Mejor aprovechamiento de la pantalla y mucho ms cmodo (no hay que volver
atrs, se puede seleccionar otro inmediatamente).
Cabe aclarar que si mantenemos este diseo para un Smartphone, la comodidad del Tablet
se pierde, pues no se podra leer bien la descripcin del pjaro al aparecer muy pequea y el
listado sera difcil de pulsar al ser muy estrecho. Por esto tiene sentido que en el mvil
tenga un diseo y funcionalidades diferentes al del Tablet.
Por cuestiones de espacio nos limitaremos al ejemplo de Smartphone y Tablet. Pero
imagina que queremos hacer esta misma aplicacin para un reloj de unas 2 pulgadas, puede
que en vez de poner un listado pusiramos un grid con las imgenes de los pjaros para que
el dedo pudiera pulsar mejor los elementos, y la descripcin aparecera aparte sin foto. O en
una televisin de 40 pulgadas imagina la cantidad de cosas que entraran; podramos, por
ejemplo, poner al lado de la descripcin un vdeo del pjaro que vuela y debajo la ficha
tcnica, todo en la misma pantalla. Esto quiere decir que nos ajustamos al tamao para
realizar el diseo y la funcionalidad.
Por suerte para nosotros, no tenemos que hacer un diseo para cada pulgada de cada
pantalla y para cada forma. Nos atendemos a la limitacin por las modas. Pongo todos los
dispositivos existentes con Android que pudiera ser bueno prestar atencin al diseo y a la
funcionalidad. Siempre claro, dependiendo del alcance de nuestra aplicacin (las pulgadas
y formas son orientativas):
Reloj (1 a 2 pulgadas, cuadrado)
Smarphone o dispositivo GPS (3 a 5 pulgadas, rectangular alargado)
Phablet (5 a 7 pulgadas, rectangular alargado)
Tablet (7 a 12 pulgadas, proporcin aurea)
Pantalla de un ordenador (14 a 30 pulgadas, rectangular alargado o proporcin aurea)
Televisin (30 a 80 pulgadas, proporcin aurea)
Proyector (80 a 300 pulgadas, proporcin aurea)
Depender del desarrollador saber a qu diseos y que funcionalidades atender en cada
momento.
Y se puede hacer esto en la misma aplicacin? o Se desarrolla una App para cada tamao
de pantalla? La respuesta es, siempre desde la perspectiva del buen programador, se debe
y se puede hacer en la misma aplicacin. Los motivos son muy simples, que seguro ests
harto de escuchar: modularidad y reusabilidad. Esto se logra con los Fragments o
Fragmentos.
Si conoces el comportamiento de las Activities (ver en http://jarroba.com/activity-entender-
y-usar-una-actividad/), advertirs que tienen un ciclo de vida y estn asociadas a una vista
(Layout en XML).
Un Fragment es un trozo (o un fragmento, si apelamos al mismo nombre que lo viste) de
una actividad. Un Fragment tiene su propio Layout y su propio ciclo de vida.
Puedes apreciar, que programndolo una vez, puedes rehusar el cdigo para que se adapte a
diferentes tamaos de pantalla con la disposicin de los elementos que quieras.
Por lo que adivinars que un Fragment siempre ha de estar en una Activity, no puede existir
independiente. Y el ciclo de vida de la Activity contenedora afectar al del Fragment; por
ejemplo, si se pausa la Activity el o los Fragments, que estn en esta actividad, sern
pausados.
Hablando del ciclo de vida de un Fragment, no podemos continuar sin dedicarle la parte
que se merece. Es el siguiente, y no te asustes de lo largo que es, si entendiste el de Activity
este es parecido (Grficos extrados
de http://developer.android.com/guide/components/fragments.html, modificados y
traducidos por www.Jarroba.com):

Para que conozcas a grandes rasgos que es lo que hace cada una de los mtodos, te los
detallo en la siguiente imagen (Referencia
en http://developer.android.com/reference/android/app/Fragment.html):

Nota: Como ya hicieramos con Activity en este otro artculo, dejo un ejemplo simple -sirve
como plantilla o snippet- de un Fragment, con todos sus mtodos (decir tiene que no todos
son obligatorios; pero el constructor vaco s que lo es, lo explico en el siguiente artculo) y
el log puesto para ver por donde va entrando:
public class Fragment_de_ejemplo extends Fragment {

private final String LOG_TAG = "test";

public Fragment_de_ejemplo() {
}

@Override
public void onAttach (Activity activity) {
super.onAttach(activity);
Log.v(LOG_TAG, "onAttach");
}

@Override
public void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v(LOG_TAG, "onCreate");
}

@Override
public View onCreateView (LayoutInflater inflater, ViewGroup
container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.miLayout,
container, false);
Log.v(LOG_TAG, "onCreateView");
/* Aqu podemos seleccionar las Views contenidas en el
Layout para trabajar con ellas, por ejemplo con:
* TipoView miView = (TipoView)
rootView.findViewById(R.id.miViewXML);
*/
return rootView;
}

@Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.v(LOG_TAG, "onActivityCreated");
}

@Override
public void onViewStateRestored (Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
Log.v(LOG_TAG, "onViewStateRestored");
}

@Override
public void onStart () {
super.onStart();
Log.v(LOG_TAG, "onStart");
}

@Override
public void onResume () {
super.onResume();
Log.v(LOG_TAG, "onResume");
}

@Override
public void onPause () {
super.onPause();
Log.v(LOG_TAG, "onPause");
}

@Override
public void onStop () {
super.onStop();
Log.v(LOG_TAG, "onStop");
}

@Override
public void onDestroyView () {
super.onDestroyView();
Log.v(LOG_TAG, "onDestroyView");
}

@Override
public void onDestroy () {
super.onDestroy();
Log.v(LOG_TAG, "onDestroy");
}

@Override
public void onDetach () {
super.onDetach();
Log.v(LOG_TAG, "onDetach");
}

}

Hemos credo conveniente dividir este artculo en dos partes por comodidad y
optimizacin. Este primero ms terico, y una segunda parte que dispone de un ejemplo
completo de como programar con Fragments para Android completamente explicado: en
la siguiente pgina, a la que puedes ir pinchando aqu mismo.


Programar Fragments (fragmentos) en
Android
Despus del primer artculo (ver primera parte aqu), continuamos donde lo dejamos y
preparados para programar. Comenzar con una descripcin ilustrada para que no quepan
dudas, o al menos sean mnimas. Continuemos donde lo dejamos.
Retomamos el ejemplo para disear el Smartphone. Veamos que tendremos una Activity
con un listado que representaremos el diseo como:

Distinguir lo verde como Fragment y lo rojo como Activity. El resto de contenido
pertenece al Layout (texto, imgenes, etc).
Y un al pulsar sobre un elemento de la lista, nos abrir una segunda Activity que ser el
detalle de la entrada:

Ahora un par de preguntas sobre la representacin del detalle de la entrada (la imagen
anterior), para ver si has entendido la teora Cuntos Layouts, es decir, ficheros XML de la
carpeta Layout, componen esta Activity? Y dnde estaran ubicados? La solucin es 2
Layouts, y estn ubicados donde se muestra en la imagen a continuacin (la letra ms
pequea en negrita con rectngulo transparente):

Si no has acertado, no te preocupes, a continuacin lo explico. Si has dado con la solucin a
la primera, me quito el sombrero, ya que has entendido la complejidad de las vistas de los
Fragments.
La Activity tiene asociado un Layout como siempre, que llamaremos
Layout_activity_detalle (engloba todo el rectngulo rojo) es la asociacin Layout con
Activity tpica. Y hemos dicho que el Fragment es como si fuera una Activity pero
pequea, con lo que tambin tiene asociado un Layout que llamamos
Layout_fragment_detalle. Espero que los nombres sean acertados y aclaratorios
Hemos dejado para el final el primero, porque tiene una particularidad. Si te hago las dos
preguntas anteriores Dnde y cuntos Layouts componen el listado? Podras decirme que
3, pero no son 3 sino 2. Fjate en la siguiente imagen un segundo y te lo explico.

La actividad tiene, como acostumbra, su Layout asociado llamado
Layout_activity_principal_listado. El Fragment no tiene fichero de Layout asociado No
me acabas de decir que s tena Layout, adems, es el fichero XML tiene un ListView
claramente? En Fragments el listado es un caso especial. Si has tocado listas un poco ms
en profundidad sabrs que si extendemos la clase, en vez de con Activity con ListActivity,
no hace falta declarar un fichero con el ListView. Con Fragments es igual si extendemos de
ListFragment. Usaremos este modo por simplificar cdigo. Y aclarar que en este Fragment
existir existe el Layout con el ListView, pero no lo haremos nosotros directamente. Ya
terminamos con el ltimo Layout, el de cada elemento de la lista llamado
Layout_elemento_listado.
Aqu acaba el diseo para dispositivos mviles.
Ahora el de la Tablet en el que me explayar menos en detalles, pasando a lo importante.
Recordamos que queremos que todo se muestra a la vez (listado y detalle).

Notars cmo estn separados los dos Fragments y que solo necesitamos una Activity.
Tambin te hago las mismas preguntas anteriores sobre los Layouts Cuntos y dnde estn
ubicados? Esta es fcil habindolo visto anteriormente.

Bueno, exista una trampa al tratarse de una sola Activity. En el diseo de mvil cada
actividad tena un Layout que contena un Fragment. En el diseo para Tablets, solo existe
una Activity que tiene asociado un Layout que contiene a los dos Fragments. Es razonable
que sea as; quera dejar clara esta diferencia.
Por cierto, estos van a ser todos los Layouts que vamos a utilizar y ninguno ms (todos los
has visto en las imgenes anteriores):

Ya llega el cdigo, tranquilo. Es importante no perderse con tanto archivo y tener las ideas
muy claras.
Previo a revelarte el cdigo XML, hay un simplismo que debes conocer. Se suele pasar por
alto y no debera, es fuente de muchos errores, por consiguiente se obtiene desesperacin al
tratar con Fragments (ya nunca ms ). El tema de Fragments estticos o finales y
dinmicos:
Un Fragment esttico o final es aquel que se declara en el fichero XML de la carpeta
Layout directamente. Este Fragment tendr la cualidad de no ser eliminado o
sustituido por nada -De lo contrario tendremos errores.
Un Fragment dinmico es el que se crea desde cdigo Java y se asocia a un
ViewGroup (Se recomienda el uso de FrameLayout). ste s que se podr eliminar o
sustituir por otro Fragment u otro contenido.
Para entenderlo bien, con el ejemplo del Tablet nos bastar.

Tenemos el listado, que es algo que siempre va a ser igual (podrn aumentar o disminuir los
elementos contenidos en el listado, pero siempre ser un listado), por lo que podemos
declarar su fragment en el XML, es esttico. Y luego tenemos la parte derecha del detalle,
dependiendo del seleccionado en el listado mostrar el detalle de un pjaro (descripcin,
nombre y foto) diferente. Con lo que cada detalle de cada pjaro tendr su propio Fragment
-si los equiparamos a las hojas de un libro, pasar cada Fragment equivaldra a pasar las
hojas del libro de pjaros- por lo que nos interesa que estos Fragments sean dinmicos. Lo
que nos dibujar el siguiente Layout con un Fragment esttico en XML y un FrameLayout
que contendr a los Fragments dinmicos.

Por lo que el cdigo de layout_activity_principal_dospaneles.xml ser:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:baselineAligned="false"
android:divider="?android:attr/dividerHorizontal"
android:orientation="horizontal"
android:showDividers="middle" >

<!--
Este fragmento esttico contiene al listado
-->
<fragment
android:id="@+id/fragment_listado"
android:name="jarroba.invarato.fragmentos.Fragment_Lista"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>

<!--
Este FrameLayout contendr un fragmento dinmico con el contenido
del elemento pulsado del listado
-->
<FrameLayout
android:id="@+id/framelayout_contenedor_detalle"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />

</LinearLayout>
Del mismo modo, para mvil, tenemos por separado el listado con el Fragment esttico.
Cuyo cdigo de layout_activity_principal_listado.xml es:
<!--
Este fragmento esttico contiene al listado
-->
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_listado"
android:name="jarroba.invarato.fragmentos.Fragment_Lista"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" />
Y por otra parte, de manera separada pero con la misma lgica al que hemos explicado de
la Tablet, tenemos el Fragment dinmico para el detalle. Paralayout_activity_detalle.xml:
<!--
Este FrameLayout contendr un fragmento dinmico con el contenido del
elemento pulsado del listado
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android
"
android:id="@+id/framelayout_contenedor_detalle"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Tambin tenemos la estructura simple de la vista de cada elemento del listado
en layout_elemento_listado.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center|left"
android:orientation="horizontal" >

<ImageView
android:id="@+id/imageView_imagen_miniatura"
android:layout_width="80dp"
android:layout_height="80dp"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:contentDescription="Descripcin del contenido de la
imagen"
android:src="@android:drawable/ic_menu_gallery" />

<TextView
android:id="@+id/textView_titulo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>
Y el del detalle, en layout_fragment_detalle.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center|top"
android:orientation="vertical" >

<TextView
android:id="@+id/textView_superior"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />

<ImageView
android:id="@+id/imageView_imagen"
android:layout_width="178dp"
android:layout_height="178dp"
android:adjustViewBounds="true"
android:contentDescription="Descripcin del contenido de la
imagen"
android:scaleType="fitXY"
android:src="@android:drawable/ic_menu_gallery" />

<TextView
android:id="@+id/textView_inferior"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Small Text"
android:textAppearance="?android:attr/textAppearanceSmall" />

</LinearLayout>
Ya tenemos las vistas. Antes de entrar con Java, tenemos que hacer una diferenciacin ms.
Necesitamos diferenciar con qu tipo de pantalla estamos tratando para poder aplicar el
diseo de mvil o de tablet. Esta diferenciacin Android la hace muy bien gracias a las
carpetas values, que estn en la carpeta res.

Tendremos 3 carpetas values (ms informacin
en http://developer.android.com/guide/practices/screens_support.html#DeclaringTabletLay
outs):
values-large: para pantallas grandes; es decir, para Tablets (Necesario para que
funcione en la versin 3 de Android). Crearemos en esta carpeta un nuevo fichero
XML llamado layout.xml (lo explico un poco ms adelante).
values-sw600dp: para pantallas con un ancho mayor a 600dp (independientemente de
la rotacin de la pantalla); para Tablets de este tamao o ms. Este valor lo podemos
cambiar, pero 600 nos va a funcionar muy bien para nuestros propsitos. Crearemos
en esta carpeta otro nuevo fichero XML tambin llamado layout.xml (lo explico un
poco ms adelante).
values: carpeta de valores para el resto de dispositivos que no cumplan las condiciones
anteriores. Lo usaran los Smartphones, o las Tablets pequeas que no cumplan el
tamao mnimo que hemos puesto. No tocamos ni aadimos nada en esta carpeta.
Hemos creado dos ficheros llamados layout.xml. Ambos contendrn el mismo contenido
que es el siguiente:
<resources>
<item name="layout_activity_principal_listado"
type="layout">@layout/layout_activity_principal_dospaneles</item>
</resources>
Esto es un truquito que te cuento para no repetir ficheros: los alias. Podramos haber creado
varias carpetas layout pero tendramos cdigo duplicado con lo mismo; con el alias
evitamos repetir cdigo innecesariamente. Este alias lo nico que hace es sustituir el
contenido de un XML por otro. As, si la pantalla es pequea cargar directamente el
XML layout_activity_principal_listado.xml en el que solo se muestra un listado; y si es
grande, el contenido de este fichero ser sustituido por el contenido del fichero
layout_acitivity_principal_dospaneles.xml que dispone un Fragment a la izquierda para
el listado y un FrameLayout a la derecha para el Fragment dinmico del detalle. Para mayor
claridad, echa un vistazo a la imagen siguiente:


Ahora ya podemos meternos de lleno con el cdigo Java. Primero te voy a mostrar la
estructura completa del proyecto, debers crear las clases Java (que detallo a continuacin)
y aadir las imgenes. De la carpeta res ya est todo terminado. De la siguiente imagen
solo hemos creado lo que est en rojo para hacer la aplicacin.

Empecemos por el cdigo primero en ejecutarse, que es Activity_Principal.java. Esta es
una Activity, pero para tratar con Fragments necesitamos un tipo de Activity especial
llamada FragmentActivity de la que extenderemos la clase. Pero antes vamos a explicar
en esencia lo que hace, que son dos cosas y luego muestro el cdigo:
Diferenciar la cantidad de elementos que maneja para cada tipo de dispositivo: En el
onCreate le asociaremos el Layout layout_activity_principal_listado.xml
recordemos que su contenido tendr nicamente un listado, o un listado y un detalle,
dependiendo del tamao de la pantalla. Para saber si estamos trabajando con dos
Fragments en la misma Acitivity, es tan sencillo como preguntar si existe el detalle,
sino existe estaremos trabajando con un solo Fragment que ser sin lugar a dudas el
listado.
Comunicar a los Fragments: Programaremos los Fragments de manera completamente
modular; es decir, un Fragment no se comunica con otro directamente sino a travs de
interfaces. Funciona del siguiente modo (para mayor claridad, echar un vistazo a la
imagen inferior que es para el caso del Tablet; para el Smartphone sera igual, pero
pasndole el dato de una Activity a la otra, y sta ya se lo comunicara al Fragment
con el detalle):

1) Se pulsa sobre un elemento del Fragment que contiene al listado. A travs de un
mtodo de Callback onEntradaSelecionada (esto es programacin por eventos, en este
artculo explicamos su comportamiento, pero resumimos al explicar el cdigo por no ser el
tema principal del artculo) comunica el id de la entrada seleccionada a la Activity que lo
engloba (de ah que implemente a Fragment_Lista.Callbacks).
2) La Activity recoge el dato. Si:
Es Tablet: crea un nuevo Fragment con el detalle, le enva el id para que cargue el
contenido apropiado y lo coloca en el FrameLayout, remplazando cualquier otro
Fragment con el detalle que pueda existir.
Es Smartphone: Crea una nueva Activity al que le enva el id. La nueva Activity
cargar el Fragment con el detalle sobre s misma.
3) Se muestra el Fragment con el detalle al usuario.
Y este es el cdigo correspondiente de esta clase:
public class Activity_Principal extends FragmentActivity implements
Fragment_Lista.Callbacks {

private boolean dosFragmentos;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.layout_activity_principal_listado);

if (findViewById(R.id.framelayout_contenedor_detalle)
!= null) {
dosFragmentos = true;
}
}

@Override
public void onEntradaSelecionada(String id) {
if (dosFragmentos) {
Bundle arguments = new Bundle();

arguments.putString(Fragment_Detalle.ARG_ID_ENTRADA_SELECIONAD
A, id);
Fragment_Detalle fragment = new
Fragment_Detalle();
fragment.setArguments(arguments);

getSupportFragmentManager().beginTransaction().replace(R.id.fr
amelayout_contenedor_detalle, fragment).commit();

} else {
Intent detailIntent = new Intent(this,
Activity_Detalle.class);

detailIntent.putExtra(Fragment_Detalle.ARG_ID_ENTRADA_SELECION
ADA, id);
startActivity(detailIntent);
}
}
}
Comencemos con un Fragment normal, que es el del detalle. Para ello escribimos el cdigo
de Fragment_Detalle.java. Por ser un Fragment normal y corriente extender de
Fragment. Explico el contenido de los mtodos:
Contructor: en los Fragments siempre vaci para poder instanciarlo.
onCreate: recoge el contenido de la entrada.
onCreateView: aqu se maneja la vista, es decir crea y se asocia con el Layout (en
Activity se hace en el onCreate con el mtodo setContentView; pero esto es un
Fragment, funciona de manera diferente y es as como se hace, con inflate(). Averigua
todo sobre inflate() en este otro artculo).
public class Fragment_Detalle extends Fragment {

public static final String ARG_ID_ENTRADA_SELECIONADA =
"item_id";
private Lista_contenido.Lista_entrada mItem;

public Fragment_Detalle() {
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

if
(getArguments().containsKey(ARG_ID_ENTRADA_SELECIONADA)) {
//Cargamos el contenido de la entrada con cierto
ID seleccionado en la lista. Se recomiendo usar un Loader para cargar
el contenido
mItem =
Lista_contenido.ENTRADAS_LISTA_HASHMAP.get(getArguments().getString(AR
G_ID_ENTRADA_SELECIONADA));
}
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container, Bundle savedInstanceState) {
View rootView =
inflater.inflate(R.layout.layout_fragment_detalle, container, false);

//Mostramos el contenido al usuario
if (mItem != null) {
((TextView)
rootView.findViewById(R.id.textView_superior)).setText(mItem.textoEnci
ma);
((TextView)
rootView.findViewById(R.id.textView_inferior)).setText(mItem.textoDeba
jo);
((ImageView)
rootView.findViewById(R.id.imageView_imagen)).setImageResource(mItem.i
dImagen);
}

return rootView;
}
}
Exporto android.support.v4.app o android.app?
A la hora de exportar la librera de Fragment (por ejemplo, aunque tambin podra darse el
caso con FragmentManager, FragmentTransaction, etc). Eclipse te dar a elegir entre las
dos opciones dos: android.app.Fragment -solo funciona a partir de Android 3.0 nivel
11- o android.support.v4.app.Fragment -para cualquier versin de Android.
Nuestra recomendacin es que uses android.support.v4.app.*.
Nunca mezcles en el mismo proyecto las dos libreras a importar (por ejemplo, que hayas
importado android.support.v4.app.FragmentManager y android.app.Fragment ), pues lo
ms probable es que te encuentres con alguna variante del siguiente error en tiempo de
ejecucin:
The method replace() in the type FragmentTransaction is not applicable for the
arguments ()
La solucin ya sabes que debes hacer: buscar y cambiar el archivo importado que no
cumple lo anterior descrito y cambiarlo por el otro (en el anterior ejemplo, nos damos
cuenta y lo cambiamos a android.support.v4.app.FragmentManager
y android.support.v4.app.Fragment ).
Entendido el Fragment normal, ahora uno especial. Implementaremos el del listado
en Fragment_Lista.java. Esta clase es un Fragment, pero es un Fragment especial que
extender de ListFragment, que es el listado preparado para ser Fragment (Aqu no
asociamos ningn Layout, pues al extender de ListFragment ya lo trae puesto). Callaback:
Tendr implementado el Callback que notifique a la Activity de que elemento del listado se
haya pulsado. Explico uno a uno los mtodos aqu usados:
Constructor: Seguro que te fijars en el constructor vaco, es necesario para el correcto
funcionamiento de los Fragments, as que ni se te ocurra quitarlo :D.
onCreate: como ya hicimos en el artculo de listado asignamos el contenido de cada
entrada a cada elemento del listado.
onAttach: Simplemente asegura que el desarrollador haya implementado el Callback,
en la clase que use a este Fragment.
onDetach: Limpia el Callback.
onListItemClick: al extender de ListFragment, es necesario sobrescribir esta clase, que
es la que escucha la pulsacin sobre un elemento de la lista. Y as usaremos el
Callback para notificar a la Actividad del id pulsado.
public class Fragment_Lista extends ListFragment {

private Callbacks mCallbacks = CallbacksVacios;

public interface Callbacks {
public void onEntradaSelecionada(String id);
}

private static Callbacks CallbacksVacios = new Callbacks() {
@Override
public void onEntradaSelecionada(String id) {
}
};

public Fragment_Lista() {
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setListAdapter(new Lista_adaptador(getActivity(),
R.layout.layout_elemento_listado, Lista_contenido.ENTRADAS_LISTA){
@Override
public void onEntrada(Object entrada, View view)
{
if (entrada != null) {
TextView texto_superior_entrada =
(TextView) view.findViewById(R.id.textView_titulo);
if (texto_superior_entrada != null)

texto_superior_entrada.setText(((Lista_contenido.Lista_entrada
) entrada).textoEncima);

ImageView imagen_entrada = (ImageView)
view.findViewById(R.id.imageView_imagen_miniatura);
if (imagen_entrada != null)

imagen_entrada.setImageResource(((Lista_contenido.Lista_entrad
a) entrada).idImagen);
}
}
});

}

@Override
public void onAttach(Activity activity) {
super.onAttach(activity);

if (!(activity instanceof Callbacks)) {
throw new IllegalStateException("Error: La
actividad debe implementar el callback del fragmento");
}

mCallbacks = (Callbacks) activity;
}

@Override
public void onDetach() {
super.onDetach();
mCallbacks = CallbacksVacios;
}

@Override
public void onListItemClick(ListView listView, View view, int
posicion, long id) {
super.onListItemClick(listView, view, posicion, id); mCallbacks.onEntradaSelecionada(Lista_contenido.ENTRADAS_LISTA.get(posicion).id);
}

}
Hasta aqu ya tenemos lo que hace funcionar la estructura de los Tablets.
Continuemos para el caso de Smartphone. Necesitamos un segundo Activity para contener
al Fragment del detalle. Llamaremos Activity_Detalle. Recuerdas que heredaba? A
Activity no, estamos trabajando con Fragments, extiende de FragmentActivity. Solo tiene
un mtodo onCreate que comprobar si ya ha creado al Fragment del detalle para cargarlo,
o no para crearlo. La creacin del Fragment del detalle es igual que en el caso de
Activity_Principal.java.
public class Activity_Detalle extends FragmentActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_activity_detalle);

// Comprobamos que previamente no hayamos entrado en
esta actividad (por ejemplo, al rotar el dispositivo). Si es as se
aade el fragmento al contenedor
if (savedInstanceState == null) {
// Crea el fragmento del detalle de la entrada y
lo aade a la actividad
Bundle arguments = new Bundle();

arguments.putString(Fragment_Detalle.ARG_ID_ENTRADA_SELECIONAD
A,
getIntent().getStringExtra(Fragment_Detalle.ARG_ID_ENTRADA_SELECIONADA
));
Fragment_Detalle fragment = new
Fragment_Detalle();
fragment.setArguments(arguments);

getSupportFragmentManager().beginTransaction().add(R.id.framel
ayout_contenedor_detalle, fragment).commit();
}
}

}
Ya solo nos queda comentar Lista_adaptador.java que encontrars en el artculo del
listado.
Y Lista_contenido.java, que contiene a la clase Lista_entrada del artculo del listado. Lo
hemos hecho as por simplificar el cdigo. Ya que si los datos no van a cambiar, as es muy
fcil hacer una estructura esttica que de elementos que siempre est visible por todas las
clases sea el momento que sea de la ejecucin. Simplemente guardamos unos listados con
el contenido de las entradas estticamente, esto se hace al inicio de la aplicacin.
public class Lista_contenido {

/**
* Donde se guardan las entradas de la lista.
*/
public static ArrayList<Lista_entrada> ENTRADAS_LISTA = new
ArrayList<Lista_entrada>();

/**
* Donde se asigna el identificador a cada entrada de la lista
*/
public static Map<String, Lista_entrada>
ENTRADAS_LISTA_HASHMAP = new HashMap<String, Lista_entrada>();

/**
* Creamos estticamente las entradas
*/
static {
aniadirEntrada(new Lista_entrada("0",
R.drawable.im_buho, "BUHO", "Bho es el nombre comn..."));
aniadirEntrada(new Lista_entrada("1",
R.drawable.im_colibri, "COLIBR", "Los troquilinos (Trochilinae)
son..."));
aniadirEntrada(new Lista_entrada("2",
R.drawable.im_cuervo, "CUERVO", "El cuervo comn (Corvus corax) es
..."));
aniadirEntrada(new Lista_entrada("3",
R.drawable.im_flamenco, "FLAMENCO", "Los fenicopteriformes..."));
aniadirEntrada(new Lista_entrada("4",
R.drawable.im_kiwi, "KIWI", "Los kiwis (Apterix, gr. 'sin alas')
son..."));
aniadirEntrada(new Lista_entrada("5",
R.drawable.im_loro, "LORO", "Las Psitcidas (Psittacidae) son..."));
aniadirEntrada(new Lista_entrada("6",
R.drawable.im_pavo, "PAVO", "Pavo es un gnero de aves..."));
}

/** Aade una entrada a la lista
* @param entrada Elemento que aadimos a la lista
*/
private static void aniadirEntrada(Lista_entrada entrada) {
ENTRADAS_LISTA.add(entrada);
ENTRADAS_LISTA_HASHMAP.put(entrada.id, entrada);
}

/**
* Representa una entrada del contenido de la lista
*/
public static class Lista_entrada {
public String id;
public int idImagen;
public String textoEncima;
public String textoDebajo;

public Lista_entrada (String id, int idImagen, String
textoEncima, String textoDebajo) {
this.id = id;
this.idImagen = idImagen;
this.textoEncima = textoEncima;
this.textoDebajo = textoDebajo;
}
}

}
Y nos falta aadir al AndroidManifest.xml la Actividad que no es la principal, es decir
Activity_Detalle. Este es mi AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="jarroba.invarato.fragmentos"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="18" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity

android:name="jarroba.invarato.fragmentos.Activity_Principal"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity

android:name="jarroba.invarato.fragmentos.Activity_Detalle"
android:label="@string/titulo_detalle_entrada"
android:parentActivityName=".Activity_Principal" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".Activity_Detalle" />
</activity>
</application>

</manifest>
Dejo aqu el cdigo funcional para descargar, bastante comentado para aclarar todava ms
las posibles dudas que queden en el tintero. Descrgalo aqu: Fragmentos
Te recomiendo que lo pruebes tanto con un emulador o dispositivo fsico- de Smartphone,
como de Tablet, para que veas como queda en cada dispositivo.
Nota: si quieres ahorrarte un montn de cdigo aprovechando ahora que entiendes la
arquitectura de los Fragments. Al crear un nuevo proyecto Android puedes seleccionar
Master/Detail Flow en la pgina Create Activity. Lo nico que, como usa ActionBar,
requiere de mnimo Android 3.0 (API 11 o Honeycomb).

Y con esto acabamos los fragmentos. La estructura mental de Fragment tiene cosas que ver
y cosas que son completamente diferentes a la de Activity. Una vez entendidas te aseguro
que son muy fciles

Context de Android
En Jarroba hemos querido recopilar y explicar con mximo detalle el Context o contexto de
Android, a razn de que el Contex es una parte fundamental a la hora de desarrollar
aplicaciones Android (Antes de continuar puede que te interese comprender algunos
conceptos bsicos como Activity en este artculo o Intent en este otro). Si eres programador
Android seguro que notars que entenderlo resulte fundamental, pero la poca informacin
respecto al tema resulte escasa por la breve documentacin, o a dar por dadas cosas que no
estn lo suficientemente explicadas. Puede que tengamos una breve idea sobre Context. Por
eso, le hemos querido dedicar un artculo a esta parte apasionante de Android. As, si nos
dirigimos a la documentacin oficial podemos leer:
Es el interfaz global de informacin acerca del entorno de la aplicacin. Es una
clase abstracta que implementa Android. Permite acceder a los recursos especficos
de la aplicacin y a sus clases, as como llamar al padre para realizar operaciones
a nivel de la aplicacin, como lanzar Activities, difundir mensajes por el sistema,
recibir Intents, etc.
(Original en http://developer.android.com/reference/android/content/Context.htm,
traduccin realizada por www.Jarroba.com)
Antes de explicar con detalle esta idea oficial -a la que te recomiendo que acudas como
resumen cuando tengas claras las ideas- seguro que te ha ocurrido el mal de muchos
programadores Android. Dicho mal ha sido creernos lo del Context y aplicarlo cada vez
que se nos pide sin saber muy bien por qu, para qu sirve realmente, cuntos ContextPero
no esta la hay, o de dnde sale. Por norma general sabemos que el contexto es el this, que
es el objeto propiamente:
Context contexto = this;
Pero si es el objeto Cmo puede ser a la vez un contexto? Todos los objetos tienen
contexto? Responderemos las preguntas a continuacin.
Si te dijera que el Context de Android es solo eso un contexto, puede que te quedes igual.
Si tampoco est muy clara la idea de la palabra contexto y te digo que cumple a la
perfeccin su segundo significado que figura en la RAE (Definicin de contexto en la
RAE):
2. m. Entorno fsico o de situacin, ya sea poltico, histrico, cultural o de cualquier
otra ndole, en el cual se considera un hecho.
Puedes que me llames hasta loco Y aunque no te puedo demostrar que est loco o no, lo
que te comento no es ninguna locura y te lo voy a aclarar.

SOBRE EL CONTEXT
14-YEAR-OLD GIRL STEALS HER MOTHER'S
HUSBAND(BWNTODAY)
Para entenderlo tenemos que volver a un pasado lejano, unos cuantos siglos atrs,
concretamente a 1492 (Esto no demuestra mi locura, es solo un ejemplo ). El ao
1492 lo englobaba todo en esa poca: casas, barcos, personas, cultura, libros, etc. Si lo
extrapolamos a las Apps de Android, diramos que 1492 es nuestra aplicacin la que
engloba todo- y que los barcos, la gente y las casas son las Activities. Todo tiene un
contexto propio y estar dentro de otro. Podemos hablar del contexto histrico de 1492 (ojo
con la palabra contexto); as, si le pidiera al contexto de 1492 que me d un barco, no me
devolvera un portaviones de motor nuclear, probablemente me devolvera una carabela,
una nao, o algn otro barco de la poca. He escogido el ao de 1492 porque me pareca
muy global, al ser el ao del descubrimiento de Amrica por Cristobal Coln; y porque es
algo histrico, que es donde ms se escucha la palabra contexto, ms concretamente
contexto histrico. Como antes mencion todo tiene un contexto propio, por ejemplo un
barco tiene su propio contexto, que ser diferente al contexto de otro barco, y muy diferente
al de un libro, pero ambos estn dentro del mismo contexto del ao 1492 .
Vamos a concretar un poco ms el ejemplo. Hemos creado una aplicacin que hemos
llamado 1492 (en la imagen siguiente vers que hemos puesto 1492.apk, el apk es la
extensin en todas las aplicaciones de Android). De momento solo nos ha dado tiempo a
crear 4 Activities. 3 Activities van a ser los barcos que Cristobal Coln us para viajar,
estos fueron: La Nia, La Pinta y La Santa Mara. Y aadimos una ltima Activity que
hemos llamado Cortes.

Si estando en la Activity La_Pinta por ejemplo, le pedimos que nos muestre los cuadros
famosos (imagina que lo que aqu llamamos cuadro famoso es un recurso drawable de
Android, es decir, un imagen) que estn en su contexto, nos devolver pinturas de la poca
estn o no estn dentro del barco (en Android seran todos las imgenes que estn en la
carpeta res). Pero algn cuadro, lo podremos comprar y colgar dentro del camarote del
capitn (para Android, comprar equivaldra a obtener la imagen por
getResources().getDrawable(), y colgar en el camarote por ejemplo al mtodo de una
View: setBackground () ), de este modo s estara el cuadro dentro del barco aunque en su
contexto existan otros.
Para ver este ejemplo en cdigo vamos a tener la siguiente estructura de carpetas (solo
usaremos la clase que hereda de Activity llamada Barco_La_Pinta.java, el resto estn
puestas para ejemplificar el mundo de 1492 del ejemplo):

Tenemos un layout que hemos llamado pared_del_camarote_del_barco_la_pinta.xml,
que contiene una ImageView (que es el hueco de la pared donde colgar el cuadro) en el
siguiente cdigo:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".Barco_La_Pinta" >

<ImageView
android:id="@+id/imageView_Barco_La_Pinta_lugarParaCuadro"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="188dp"
android:src="@drawable/ic_launcher" />

</RelativeLayout>
Y el cdigo java de Barco_La_Pinta.java es:
public class Barco_La_Pinta extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.pared_del_camarote_del_barco_la_pinta)
;

ImageView iv = (ImageView)
findViewById(R.id.imageView_Barco_La_Pinta_lugarParaCuadro);

Context contexto = this;

Drawable cuadroElegido =
contexto.getResources().getDrawable(R.drawable.cuadro_torre);

iv.setBackground(cuadroElegido); //Nota: Si se usa un
Api Level anterior a 16 usar setBackgroundDrawable()
}

}
En Android, cuando la documentacin oficial se refiere a interfaz global de informacin
acerca del entorno de la aplicacin, quiere decir que nos proporciona a los
programadores acceso a mtodos que nos facilitan la vida; como lanzar nuevas
Activities con startActivity() (A qu no programas cada lnea de cdigo al lanzar una
aplicacin? Simplemente llamas a este mtodo y se acab). U obtener recursos de la carpeta
res (como a las imgenes, colores, textos, etc) con getResources() o los Strings con
getString(), obtener los datos almacenados en local con getSharedPreferences(), entre otros
muchos.
Volvamos al ejemplo, Pero si le pregunto al contexto de 1492 por los cuadros famosos, no
nos devolvera los mismos? S, los mismos. Pero no es esta la causa por lo que se
diferencian los contextos, existen cosas comunes.
Al contexto de cualquier barco le puedo preguntar Cmo de ajetreado est el mar? y nos
responder, pero el de la corte nunca le voy a poder hacer esa pregunta no est en el
mar! (En Android no es lo mismo el contexto de una Activity al que le puedo preguntar por
el Layout asociado, que de un Servicio que no puedo preguntarle por el Layout porque no
tiene ninguno).
Entonces, en Android nos encontramos con los siguientes tres diferentes tipos de
contextos:
Aplicacin (Como es lgico, al cubrir todo el ciclo de vida de la aplicacin desde que la
arrancamos hasta que muere, cada aplicacin tiene un nico contexto de aplicacin; adems,
este contexto engloba a todos los dems): Crea una instancia Singleton que se crea al iniciar
el proceso de la aplicacin. Se puede acceder desde una Activity o un Service con
getApplication(), o desde cualquiera que herede de Context con getApplicationContext().
Activity o Service: Heredan de ContextWrapper que a su vez hereda de Context.
ContextWrapper hace que se apodere de todas las llamadas y las enve a una instancia oculta
de Context (conocido como Base Context)
Los siguientes componentes fundamentales de Android no heredan de Context, pero lo
necesitan, por lo que el sistema se los pasa de algn modo:
BroadcastReceiver: Pero se le pasa un Context en el onReceive() cada vez que un nuevo
evento difundido por el sistema entra.
ContentProvider: Puede acceder al Context con getContext() y se le devolver el Context de
la aplicacin que lo est ejecutando (puede ser la misma aplicacin u otra diferente).
En el ejemplo, si un barco es destruido, su contexto muere con l. As, en Android el
Context est ligado al ciclo de vida del elemento que cubre, desde el momento que est en
ejecucin hasta que termina.
Siendo un poco ms tcnicos. Context es una clase abstracta que implementa
Android. Los elementos que tienen Context heredan de la clase Context. Por lo que y
respondiendo a la preguntas del principio- ni todos los objetos tienen Context, y ni el objeto
es el propio Context, depende de si heredan de Context o no.
Nota sobre la herencia: Si no entiendes muy bien la documentacin, te recomiendo que
eches un vistazo a las diferentes documentaciones (Por facilitar, hemos puesto los links de
las documentaciones en cada uno de los elementos anteriores). Por ejemplo, a la
documentacin de Activity (ver en la documentacin oficial de Activity). Vemos en la
cabecera como efectivamente hereda de Context:



SUELEN PEDIR EL CONTEXT
Normalmente piden el Context:
Al acceder a los recursos como imgenes, Strings, etc
contexto.getResources().getDrawable(R.drawable.imagen_en_los_recursos)
;
Al crear nuevos Views, Listeners, Adapters, Intents, etc. Por ejemplo:
TextView miTexto = new TextView(contexto);

Intent intento = new Intent(contexto, claseActivityArrancar.class);
Al acceder directamente a componentes como ActionBar, Intents, etc
contexto.getIntent();

OBTENER EL CONTEXT
Hemos explicado cmo obtener el Context dependiendo del tipo. Aqu dejo una lista de las
diferentes maneras de obtener el Context con ejemplos completos:
Una clase que hereda de Context (Como desde una Activity o Service): this
public class ObtenerContexto extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Context contexto = this;
}

}
Una clase que hereda de Context desde una clase annima: ClaseActivity.this
public class ObtenerContexto extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Button boton = (Button)
findViewById(R.id.button_obtenerContext_boton);
boton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Context contexto = ObtenerContexto.this;
}

});

}

}
Una clase que NO hereda de Context (como desde View): mi_view.getContext()
public class ObtenerContexto extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Button boton = (Button)
findViewById(R.id.button_obtenerContext_boton);

Context contexto = boton.getContext();
}

}
La aplicacin (desde cualquier clase que hereda de Context): getApplicationContext()
public class ObtenerContexto extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Context contexto = getApplicationContext();
}

}
Otro Context (desde una clase que hereda de ContextWrapper, como Activity):
getBaseContext()
public class ObtenerContexto extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Context contexto = getBaseContext();
}

}
La Activity del Fragment que lo contiene (desde un Fragment): getActivity()
public class obtenerContextoFragment extends Fragment {

@Override
public void onAttach (Activity activity) {
super.onAttach(activity);

Context contexto = getActivity();
}

}

EVITAR PROBLEMAS CON EL CONTEXT
Ahora solo queda evitar las fugas de memoria que el Context nos puede provocar. Lo
primero que tenemos que repasar es que un Context vive tanto como el elemento al que
pertenece, por lo que depende del ciclo de vida. As, un Context de una Activity vivir el
mismo tiempo que esta, y el Context de la aplicacin vive hasta que se termina por
completo la aplicacin (hasta que muere, no hasta que se pausa).
Aunque suene un poco contradictorio, por norma general siempre hay que usar el Context
ms pequeo que suele ser el del elemento al que pertenece; pero en la mayora de casos se
obtiene prdida de memoria, siendo altamente recomendable usar el Context de la
aplicacin. Esto sucede por el tema de la doble referencia, es decir un objeto apunta a otro
objeto y el Garbage Collection (recolector de basura de Java, para la liberacin automtica
de memoria) no puede eliminar dichos objetos, lo que implica no poder liberar esa memoria
aunque no haya nada ms apuntando a dichos objetos ms que el uno al otro.
Imaginemos que queremos guardar en una variable esttica una imagen de fondo para no
tener que estar accediendo todo el rato a la memoria cada vez que giramos el dispositivo
(recuerdo rpidamente que al girar el dispositivo se destruye la actividad y se vuelve a
crear, si la variable es esttica siempre estar en memoria aunque sea destruida), con esto el
cdigo ira mucho ms rpido:
public class miActivity extends Activity {

private static Drawable sFondoDelTexto;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Context contexto = this;

TextView label = new TextView(contexto);
label.setText("Texto con fondo");

if (sFondoDelTexto == null) {
sFondoDelTexto =
getDrawable(R.drawable.mi_imagen);
}

label.setBackgroundDrawable(sFondoDelTexto);

setContentView(label);
}

}
El problema es que le ponemos el Context como this al TextView, y al TextView le
asignamos una imagen que no va a ser destruida al rotar el dispositivo. Como esta imagen
apunta al objeto TextView, y la imagen no va a ser destruida, no se destruir el TextView,
as no se destruir el Context, por lo que no se destruir la Activity que est ligado al
Context. Aqu tenemos el problema de memoria, pues al volverse a crear, la imagen
apuntar a otro Context de otra Activity creada; y as en cada giro del mvil, hasta que nos
quedemos sin memoria y de error.
Para solucionar este caso lo mejor es usar el contexto de la aplicacin (Usando
Context.getApplicationContext() o con Activity.getApplication() ) ya que no est asociado
al ciclo de vida de la Activity, por lo que al destruirse el Context de la Activity quedar
libre cuando tenga que ser destruida y podr ser recolectada:
public class miActivity extends Activity {

private static Drawable sFondoDelTexto;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Context contexto = getApplicationContext();

TextView label = new TextView(contexto);
label.setText("Texto con fondo");

if (sFondoDelTexto == null) {
sFondoDelTexto =
getDrawable(R.drawable.mi_imagen);
}

label.setBackgroundDrawable(sFondoDelTexto);

setContentView(label);
}

}
Tambin hay que tener cuidado al crear una clase Singleton que guarde nuestro Context
(desde Jarroba no recomendamos guardar un Context ni con Singleton ni con variables
estticas, el Context se ha de pasar siempre para no perder su control). Pues si la Activity es
destruida nunca se borrar de memoria, ya que como el ejemplo anterior, existir una doble
referencia que no permita al Garbage Collector liberar dicha memoria, por lo que la
Activity seguir ocupando toda la memoria pese a estar destruida:
public class miSingleton {

private static miSingleton sInstancia;

private Context mContexto;

public static miSingleton getInstance(Context contexto) {
if (sInstancia == null) {
sInstancia = new miSingleton(contexto);
}

return sInstancia;
}

private miSingleton(Context contexto) {
mContexto = contexto;
}

}
Para corregir esto, se puede usar el Context de la aplicacin otra vez (aunque recordemo
que el Context de una aplicacin est guardado en una clase Singleton a su vez, con lo qu
Realmente necesitamos guardarlo de esta manera o con obtenerlo nos basta?):
public class miSingleton {

private static miSingleton sInstance;

private Context mContexto;

public static miSingleton getInstance(Context contexto) {
if (sInstance == null) {
sInstancia = new
miSingleton(contexto.getApplicationContext());
}

return sInstancia;
}

private miSingleton(Context contexto) {
mContexto = contexto;
}

}
Con esto terminamos con un resumen del Context: sirve para abstraer de muchas cosas que
las hace el sistema operativo por nosotros, as se hace la labor del desarrollador mucho ms
simple. Siempre que entendamos el Context y sus implicaciones.
Esperamos que el artculo haya servido para aclarar muchos conceptos. No ha sido un
artculo fcil por la escasa informacin que existe sobre el tema. Por esta razn lo
modificaremos con el tiempo, para que sea todava ms aclaratorio tanto por el feedback
que nos vayis aportando, como por las novedades que vayan saliendo del mundo Android.
Si quieres ver algunos ejemplos ms en donde se aplica Context puedes ver el artculo de
listado o en el artculo de fragments.
Referencias:
Doubleencore: http://www.doubleencore.com/2013/06/context/
Android Developer: http://developer.android.com/reference/android/content/Context.html
Android Deveolper Blog: http://android-developers.blogspot.com.es/2009/01/avoiding-
memory-leaks.html

Intent Pasar datos entre Activities
App Android (Video)
En este tutorial se va a mostrar el IDE de eclipse para realizar una App en Android y como
pasar datos de un activity a otro tras un evento o dicho de otra forma, como pasar datos de
una pantalla a otra tras pulsar un botn. Pare realizar este tutorial se necesitar tener y saber
lo siguiente:
Se ha de tener instalado el IDE Eclipse y tenerlo vinculado con el SDK de Android. Para los
que no tengis hecho esto lo podeis hacer siguiendo el siguiente tutorial:(Instalar el SDK de
Android y vincularlo con Eclipse)
Se ha de tener el Eclipse configurado correctamente. En este caso solo se necesitara tener
configurado el emulador del mvil aunque tambin es conveniente tener configurada la
consola de salida de datos llamada LogCat para poder realizar trazas en el desarrollo de la
App. Para los que no tengis configurado el Eclipse, podeis ver como se hace en el siguiente
tutorial:(Preparar las herramientas necesarias para programar en Android)
Por ltimo, aunque no es necesario pero si recomendable, debis de mirar el siguiente
tutorial (Activity entender y usar una Actividad) para entender el ciclo de vida de un
activity. No es necesario que lo mireis para realizar este tutorial y quizas si sois nveles en
el desarrollo de Apps os cueste entenderlo a la primera , pero si que es muy recomendable
para que posteriormente entendis muchas cosas en el desarrollo de Apps.
Es objectivo de este tutorial (a parte de mostrar el IDE y los archivos que hay en un
proyecto) se pretende hacer la siguiente app, que consiste en recoger unos datos del primer
activity y mostrarlos en el segundo, tal y como se muestra en la siguiente imagen:

Una vez vista la funcionalidad que ha de tener esta app, mostramos el video de como
realizar esta App desde Cero:

El proyecto realizado en este Video-Tutorial, lo podeis descargar pulsando AQUI.
Como se ha visto en este tutorial (A parte de crear las interfaces que lleva bastante tiempo),
la clave para pasar los datos de un activity a otro, es crearse un Intent para pasar los datos
de un activity a otro. Este Intent se ha declarado dentro del cdigo que define el evento que
se ha de realizar tras pulsar el botn; es decir en el OnClickListener. La parte del cdigo
donde se describe esta accin y se declara el Intent es el siguiente:
miBoton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent
(PrimerActivity.this, SegundoActivity.class);
i.putExtra("nombre",
campoNombre.getText()+"");
i.putExtra("apellido",
campoApellidos.getText()+"");
startActivity(i);
}
});
Como se observa, en el intent se declaran dos variable, nombre y apellido (lo pongo
entre comillas dobles porque en realidad no es as, pero lo digo de esta forma para que se
entienda) que se pasan al segundo activity (Intent i = new Intent
(PrimerActivity.this, SegundoActivity.class)) tras ejecutarse el mtodo startActivity(i).
Cuando el Intent i llega al segundo activity, hay que asignar los datos que hay en el
activity a alguna variable o elemento del segundo activity. Es recomendable, aunque no
necesario que se asigne lo que se obtiene de un Intent a variables para que sea el cdigo
mas legible y entendible. Recogemos los datos en el segundo activity de la siguiente
forma:
String nombre = getIntent().getStringExtra("nombre");
String apellidos =
getIntent().getStringExtra("apellido");
Despus de recoger los datos los mostramos en la pantalla en los TextView
correspondientes.
Esto ha sido todo, esperamos que este tutorial os sirva de ayuda
Entradas Relacionadas
Introduccin a Android Studio (Video)

Preparar las herramientas necesarias para programar en Android

Error Android No se encuentra el SDK de android

UITableView en Objective-C -Ejemplo- (Video)



ListView o listado en Android
Este tutorial est indicado para todos lo que ya hayan buceado un poco en Android. Se dar
por sentado ciertos conocimientos muy bsicos, cuyo apoyo pueden servirse de tutoriales
anteriores como el de saber qu es una Actividad. Si no tienes mucho tiempo o quieres un
Snippet de cdigo para hacer un listado rpidamente, entonces te recomiendo que vayas
directamente al artculo de listado en pocas lneas; si por el contrario quieres aprenderlo
todo sobre listados de Android continuar leyendo es la opcin correcta.
Aunque todo en el universo tienda al caos, siempre es bueno ponerle un orden para saber
interpretarlo. No es la mejor definicin de listado, pero si una bonita alegora al mismo.
Un listado es eso, un conjunto de datos ordenados, para que sea sencillo indagar en ellos.
Este tutorial se basar en describir como hacer un listado en Android: en el que tenemos un
nmero arbitrario de datos -nmero exacto de entradas que no conocemos, bien porque
obtengamos los datos de Internet, o estn en una base de datos que va creciendo, etc- de
aves que queremos ordenar en un listado. Cuyas entradas queremos hacer a nuestro antojo
con el nombre del ave como titular, una pequea descripcin y una imagen asociada a cada
uno (Vase la imagen siguiente, para entender de un vistazo lo que se quiere conseguir).

Y no contentos con esto, queremos que adems sea seleccionable cada elemento del listado.

Para mostrar ms informacin en un Toast (tambin podramos abrir otra Activity con
informacin extra, o lo que queramos) del elemento seleccionado.

Vamos, que construiremos un ListView de generacin dinmica de contenidos (Un ejemplo
esttico lo tienes en la pgina oficial de desarrolladores de Android), deseable el 90% de la
veces por un programador Android. Y s, las imgenes y textos del ejemplo estn obtenidos
de la Wikipedia.
Como haremos esto de una manera sencilla y ptima. Primero lo entenderemos y luego lo
haremos.
Qu es lo que queremos hacer? Queremos un listado de todos los elementos/entradas
individuales que me den la gana (entre cero e infinito ). De lo real al concepto mental
sera la siguiente imagen.

Todos las entradas son iguales, Sera maravilloso que se pudiera disear una nica entrada
y luego que el resto sean un copiar y pegar? Aunque sea por vaguera, la respuesta es:
debemos como buenos programadores.

Ya tenemos dividido lo que queremos hacer. Ahora, la lgica nos dice que en el diseo
hacia delante, tendremos dos Layouts uno principal que contendr varias veces la copia del
segundo:
Uno con la entrada suelta, con el diseo que queramos. Ser la unidad que se copiar en el
interior del listado. Lo llamaremos en este ejemplo entrada.xml.
Otro con el listado, que solo dispondr de tal. Con los huecos esperando para contener la
copia del diseo de la entrada; y cada entrada con unos datos diferentes. A este contenedor
de entradas lo llamaremos listado.xml.

Haremos el diseo de entrada.xml. Para el ejemplo haremos el siguiente Layout, que
evidentemente podremos hacer a nuestro antojo, con los campos que queramos, imgenes,
botones, checkbox, spinner, etc. Al disear ste, pensemos, no en el contenido de cada
entrada, sino como haremos todas las entradas para que salgan iguales. Pues este ser
replicado para todas la entradas.
Para el ejemplo, la idea de una entrada es la siguiente:

Y su cdigo asociado para generar la vista de una entrada sera este (Nota: por reducir
cdigo y que se entienda mejor, hemos optado por poner los Strings directamente; esto est
mal hecho y deberan ir al fichero strings.xml). Evidentemente ponemos los id para
luego referenciarlos y llenar cada una de las entradas con sus datos correspondientes.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<ImageView
android:id="@+id/imageView_imagen"
android:layout_width="80dp"
android:layout_height="80dp"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:contentDescription="Descripcin del contenido de la
imagen"
android:src="@android:drawable/ic_menu_gallery" />

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >

<TextView
android:id="@+id/textView_superior"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge"
/>

<TextView
android:id="@+id/textView_inferior"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Small Text"
android:textAppearance="?android:attr/textAppearanceSmall"
/>

</LinearLayout>

</LinearLayout>
Fcil? No. Ms fcil es listado.xml. En este ejemplo nos bastar con que usemos
ListView, que ser el contenedor de las entradas.
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ListView_listado"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
Falta que hagamos la lgica del programa. La lgica que nos cargar los datos y nos
construir el listado. Para esto tendremos una Actividad que ser la que muestre el listado.
Para no liar las cosas lo haremos en el ejemplo en la clase MainActivity.java. Esta har
uso de otras dos. Una que encapsule los datos de la entrada, cuyo nombre pondremos como
Lista_entrada.java. Y otra que ser la que adapte las entradas a la lista, y ser nombrada
como Lista_adaptador.java.
Terminaremos teniendo los siguientes archivos en el explorador de paquetes. Donde los
marcados sern los que usaremos en este ejemplo. Cabe indicar que las imgenes las
estamos insertando directamente para no complicar ms el ejemplo, pero esta forma de
construir el listado dinmicamente tambin funcionara si las imgenes se descargaran de
internet, se obtuvieran de la memoria del telfono, etc.

Empezaremos a definir Lista_entrada.java. Para qu sirve? Sabemos que nos llegarn
unos datos, y que nos interesan los siguientes para cada entrada: imagen, ttulo y
descripcin. Por lo que haremos unos paquetes de datos para cada uno de los conjuntos de
la entrada. Estos paquetes sern objetos de la clase Lista_entrada.java.

Para hacernos una idea, imaginemos que tenemos tres pjaros. Cada uno con: ttulo,
descripcin e imagen. Tendremos tres objetos de la clase Lista_entrada.java, cada uno
almacenar sus datos. Pero no confundamos, esto no est asignado todava a la entrada de
la vista -de la interfaz- sino que son grupos para separar la informacin. Estos grupos se
suelen llamar manejadores o en ingls handler.

El cdigo siguiente contiene lo que es la encapsulacin de los datos, que coinciden con los
explicados:
Ttulo, con nombre de variable como textoEncima para especificar en cul de los dos
TextViews de la vista tendr que ser colocado.
Descripcin, la variable la llamaremos como textoDebajo.
Imagen, y almacenaremos la variable idImagen, para referenciara a la imagen. Solo
guardaremos el id, ya que solo guardaremos el identificador de la imagen y no la imagen en
s (para este ejemplo no lo complicamos y guardamos el identificador, pero si queremos
podremos guardar un Drawable, un Bitmap, etc).
Este manejador tendr las variables de los View que hayamos declarado en el Layout
entrada.xml. Repito, aqu no lo referenciaremos, es solo un contenedor que separa unos
datos de otros.
Si nos fijamos en el su cdigo, solo son variables, con sus getters y de setter el mismo
constructor. No tiene ms la clase, es as de simple (aqu, para que se entienda mejor,
ponemos los getters y setters; Android recomienda por optimizar hacer variables globales
publicas y olvidarnos de getters y setters, con lo que sera todava mucho ms simple este
cdigo).
package jarroba.ramon.listado;

public class Lista_entrada {
private int idImagen;
private String textoEncima;
private String textoDebajo;

public Lista_entrada (int idImagen, String textoEncima, String
textoDebajo) {
this.idImagen = idImagen;
this.textoEncima = textoEncima;
this.textoDebajo = textoDebajo;
}

public String get_textoEncima() {
return textoEncima;
}

public String get_textoDebajo() {
return textoDebajo;
}

public int get_idImagen() {
return idImagen;
}
}
Cmo encapsulamos los datos que queramos en este Handler? Muy sencillo, ya vers.
Si creamos el objeto Lista_entrada tal cual, lo haramos de la siguiente manera:
new Lista_entrada(R.drawable. imagen, "TTULO", "Descripcin");
Dnde asignamos el objeto? Cuntos objetos vamos a tener de estos? La respuesta es en
una lista de Java, ms concretamente en un ArrayList.
En este ejemplo lo haremos directamente sobre la clase MainActivity.java como ejemplo
la siguiente (Nota: lo que se muestra a continuacin es un trozo de la clase
MainActivity.java, se muestra completa al final del artculo). Aqu un ejemplo de
como aadir la informacin de las tres aves al ArrayList:
package jarroba.ramon.listado;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;

public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listado);

ArrayList<Lista_entrada> datos = new
ArrayList<Lista_entrada>();

datos.add(new Lista_entrada(R.drawable.im_buho, "BUHO", "Bho
es el nombre comn de aves de la familia Strigidae, del orden de las
estrigiformes o aves rapaces nocturnas. Habitualmente designa especies
que, a diferencia de las lechuzas, tienen plumas alzadas que parecen
orejas."));
datos.add(new Lista_entrada(R.drawable.im_colibri, "COLIBR",
"Los troquilinos (Trochilinae) son una subfamilia de aves apodiformes
de la familia Trochilidae, conocidas vulgarmente como colibres,
quindes, tucusitos, picaflores, chupamirtos, chuparrosas,
huichichiquis (idioma nahuatl), mainumby (idioma guaran) o guanumby.
Conjuntamente con las ermitas, que pertenecen a la subfamilia
Phaethornithinae, conforman la familia Trochilidae que, en la
sistemtica de Charles Sibley, se clasifica en un orden propio:
Trochiliformes, independiente de los vencejos del orden Apodiformes.
La subfamilia Trochilinae incluye ms de 100 gneros que comprenden un
total de 330 a 340 especies."));
datos.add(new Lista_entrada(R.drawable.im_cuervo, "CUERVO",
"El cuervo comn (Corvus corax) es una especie de ave paseriforme de
la familia de los crvidos (Corvidae). Presente en todo el hemisferio
septentrional, es la especie de crvido con la mayor superficie de
distribucin. Con el cuervo de pico grueso, es el mayor de los
crvidos y probablemente la paseriforme ms pesada; en su madurez, el
cuervo comn mide entre 52 y 69 centmetros de longitud y su peso
vara de 0,69 a 1,7 kilogramos. Los cuervos comunes viven generalmente
de 10 a 15 aos pero algunos individuos han vivido 40 aos. Los
juveniles pueden desplazarse en grupos pero las parejas ya formadas
permanecen juntas toda su vida, cada pareja defendiendo un territorio.
Existen 8 subespecies conocidas que se diferencian muy poco
aparentemente, aunque estudios recientes hayan demostrado diferencias
genticas significativas entre las poblaciones de distintas
regiones."));
}

}
Todava no hemos acabado con la clase MainActivity.java. Faltara decirle que queremos
hacer con el ArrayList, que ser envirselo a la lista para que lo reconstruya y la de forma.
A toda ListView hay que pasarle un adaptador con los datos y que herede de
BaseAdapter (Son cosas de Android).
Antes un inciso. Hemos trabajado y conocemos la pesadez de hacer el adaptador de un
listado de manera dinmica. Por eso www.jarroba.com quiere haceros un regalo, con el
siguiente ahorro de tiempo y de comerse la cabeza. En todos los ejemplos que he visto por
ah, construyen un adaptador independiente para cada handler para este tipo de listas
simples. Y yo he dicho: no, nunca ms, no es necesario, un solo adaptador vale para todas
las listas con entradas personalizadas que queramos (o al menos todas con las que he
trabajado). A continuacin les regalo el cdigo, que en apariencia es sencillo; lo que s es
muy fcil de utilizar. Es el trabajo de mucho tiempo, errores y experiencia. Puede que sea
mejorable, por lo que si descubres y nos lo quieres contar, o descubro una manera mejor
actualizar este tutorial. Pero por ahora no he visto nada ms cmodo para trabajar con
listas. Por supuesto, eres libre de modificarlo, proponer mejoras y de usarlo. Nota: este
adaptador universal es solo para listas simples con vistas complejas, lo que es que van a
cargarse un vez los elementos de la lista y ya no se van a modificar ms mientras el
usuario interaccione con la lista; si queremos aadir o eliminar elementos mientras el
usuario toca la lista, requerimos de otro tipo de adaptador (Puedes aprender como utiliza
inflate() el mtodo getView() del Adapter en este otro tutorial).
Cdigo de la clase Lista_adaptador.java:
package jarroba.ramon.listado;

import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

/** Adaptador de ListView universal, para www.jarroba.com
* @author Ramon Invarato Menndez
*/
public abstract class Lista_adaptador extends BaseAdapter {

private ArrayList<?> entradas;
private int R_layout_IdView;
private Context contexto;

public Lista_adaptador(Context contexto, int R_layout_IdView,
ArrayList<?> entradas) {
super();
this.contexto = contexto;
this.entradas = entradas;
this.R_layout_IdView = R_layout_IdView;
}

@Override
public View getView(int posicion, View view, ViewGroup pariente) {
if (view == null) {
LayoutInflater vi = (LayoutInflater)
contexto.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R_layout_IdView, null);
}
onEntrada (entradas.get(posicion), view);
return view;
}

@Override
public int getCount() {
return entradas.size();
}

@Override
public Object getItem(int posicion) {
return entradas.get(posicion);
}

@Override
public long getItemId(int posicion) {
return posicion;
}

/** Devuelve cada una de las entradas con cada una de las vistas a
la que debe de ser asociada
* @param entrada La entrada que ser la asociada a la view. La
entrada es del tipo del paquete/handler
* @param view View particular que contendr los datos del
paquete/handler
*/
public abstract void onEntrada (Object entrada, View view);

}
Este cdigo lo que hace es crear un adaptador para ListView. En el constructor hay que
pasarle el contexto de la aplicacin, el id del layout de la entrada (en este ejemplo
R.layout.entrada), y el ArrayList que construimos anteriormente con los handler con los
datos. Como es obvio, ya que pide los datos del ArrayList, este cdigo ir justo despus de
la creacin del ArrayList. Al crear el objeto se nos pedir sobrescribir el mtodo
onEntrada, que ser donde asignaremos cada parte del handler de la clase
Lista_entrada.java a cada una de las copias de las vistas entrada.xml. onEntrada da
de informacin: el objeto con solo los datos de la entrada que va a construir y la vista donde
lo va a meter. Te sorprender el escaso cdigo que hay que usar y lo simple que es su uso, a
continuacin lo veremos.
Una vista rpida de donde se usa este adaptador.

En el ejemplo lo situaremos dentro del MainActivity.java en el onCreate, despus del
cdigo que ya haba (Nota: como comentamos anteriormente, al final publicaremos el
cdigo completo). Cdigo para usar el adaptador:
ListView lista = (ListView) findViewById(R.id.ListView_listado);
lista.setAdapter(new Lista_adaptador(this, R.layout.entrada,
datos){
@Override
public void onEntrada(Object entrada, View view)
{
TextView texto_superior_entrada =
(TextView) view.findViewById(R.id.textView_superior);

texto_superior_entrada.setText(((Lista_entrada)
entrada).get_textoEncima());

TextView texto_inferior_entrada =
(TextView) view.findViewById(R.id.textView_inferior);

texto_inferior_entrada.setText(((Lista_entrada)
entrada).get_textoDebajo());

ImageView imagen_entrada = (ImageView)
view.findViewById(R.id.imageView_imagen);

imagen_entrada.setImageResource(((Lista_entrada)
entrada).get_idImagen());
}
});
Este poco de cdigo usa el adaptador. Se asigna cada View con su dato en el momento justo
en el que se construye cada entrada No dije que era fcil?.
Ya solo queda capturar el evento de Click para cada una de las entradas y hacer lo que
sea con esta. En este ejemplo recogemos la descripcin y la mostramos en un Toast. Esto
lo hacemos al devolver el adaptador y conociendo la posicin nos habr devuelto la entrada
pulsada. Despus del anterior cdigo escribimos el escuchador del evento click como se
hace normalmente:
lista.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> pariente, View view, int
posicion, long id) {
Lista_entrada elegido = (Lista_entrada)
pariente.getItemAtPosition(posicion);

CharSequence texto = "Seleccionado: " +
elegido.get_textoDebajo();
Toast toast = Toast.makeText(MainActivity.this, texto,
Toast.LENGTH_LONG);
toast.show();
}
});
Y ya al fin, el cdigo completo del MainActivity.java, es el siguiente:
package jarroba.ramon.listado;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

private ListView lista;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listado);

ArrayList<Lista_entrada> datos = new
ArrayList<Lista_entrada>();

datos.add(new Lista_entrada(R.drawable.im_buho, "BUHO", "Bho
es el nombre comn de aves de la familia Strigidae, del orden de las
estrigiformes o aves rapaces nocturnas. Habitualmente designa especies
que, a diferencia de las lechuzas, tienen plumas alzadas que parecen
orejas."));
datos.add(new Lista_entrada(R.drawable.im_colibri, "COLIBR",
"Los troquilinos (Trochilinae) son una subfamilia de aves apodiformes
de la familia Trochilidae, conocidas vulgarmente como colibres,
quindes, tucusitos, picaflores, chupamirtos, chuparrosas,
huichichiquis (idioma nahuatl), mainumby (idioma guaran) o guanumby.
Conjuntamente con las ermitas, que pertenecen a la subfamilia
Phaethornithinae, conforman la familia Trochilidae que, en la
sistemtica de Charles Sibley, se clasifica en un orden propio:
Trochiliformes, independiente de los vencejos del orden Apodiformes.
La subfamilia Trochilinae incluye ms de 100 gneros que comprenden un
total de 330 a 340 especies."));
datos.add(new Lista_entrada(R.drawable.im_cuervo, "CUERVO",
"El cuervo comn (Corvus corax) es una especie de ave paseriforme de
la familia de los crvidos (Corvidae). Presente en todo el hemisferio
septentrional, es la especie de crvido con la mayor superficie de
distribucin. Con el cuervo de pico grueso, es el mayor de los
crvidos y probablemente la paseriforme ms pesada; en su madurez, el
cuervo comn mide entre 52 y 69 centmetros de longitud y su peso
vara de 0,69 a 1,7 kilogramos. Los cuervos comunes viven generalmente
de 10 a 15 aos pero algunos individuos han vivido 40 aos. Los
juveniles pueden desplazarse en grupos pero las parejas ya formadas
permanecen juntas toda su vida, cada pareja defendiendo un territorio.
Existen 8 subespecies conocidas que se diferencian muy poco
aparentemente, aunque estudios recientes hayan demostrado diferencias
genticas significativas entre las poblaciones de distintas
regiones."));
datos.add(new Lista_entrada(R.drawable.im_flamenco,
"FLAMENCO", "Los fenicopteriformes (Phoenicopteriformes), los cuales
reciben el nombre vulgar de flamencos, son un orden de aves neognatas,
con un nico gnero viviente: Phoenicopterus. Son aves que se
distribuyen tanto por el hemisferio occidental como por el hemisferio
oriental: existen cuatro especies en Amrica y dos en el Viejo Mundo.
Tienen crneo desmognato holorrino, con 16 a 20 vrtebras cervicales y
pies anisodctilos."));
datos.add(new Lista_entrada(R.drawable.im_kiwi, "KIWI", "Los
kiwis (Apterix, gr. 'sin alas') son un gnero de aves paleognatas
compuesto por cinco especies endmicas de Nueva Zelanda.1 2 Son aves
no voladoras pequeas, aproximadamente del tamao de una gallina.
Antes de la llegada de los humanos alrededor del ao 1300, en Nueva
Zelanda los nicos mamferos que haba eran murcilagos, y los nichos
ecolgicos que en otras partes del mundo eran ocupados por animales
tan diversos como caballos, lobos y ratones fueron utilizados en Nueva
Zelanda por pjaros (y en menor proporcin por ciertas especies de
reptiles). La denominacin kiwi es maor, idioma del pueblo homnimo
de linaje malayopolinesio que coloniz Nueva Zelanda antes de la
llegada de los europeos."));
datos.add(new Lista_entrada(R.drawable.im_loro, "LORO", "Las
Psitcidas (Psittacidae) son una familia de aves psitaciformes
llamadas comnmente loros o papagayos, e incluye a los guacamayos, las
cotorras, los periquitos, los agapornis y formas afines."));
datos.add(new Lista_entrada(R.drawable.im_pavo, "PAVO", "Pavo
es un gnero de aves galliformes de la familia Phasianidae, que
incluye dos especies, el pavo real comn (Pavo cristatus) y el pavo
real cuelliverde (Pavo muticus).1"));
datos.add(new Lista_entrada(R.drawable.im_pinguino,
"PINGINO", "Los pinginos (familia Spheniscidae, orden
Sphenisciformes) son un grupo de aves marinas, no voladoras, que se
distribuyen nicamente en el Hemisferio Sur, sobre todo en sus altas
latitudes."));

lista = (ListView) findViewById(R.id.ListView_listado);
lista.setAdapter(new Lista_adaptador(this, R.layout.entrada,
datos){
@Override
public void onEntrada(Object entrada, View view)
{
if (entrada != null) {
TextView texto_superior_entrada =
(TextView) view.findViewById(R.id.textView_superior);
if (texto_superior_entrada != null)

texto_superior_entrada.setText(((Lista_entrada)
entrada).get_textoEncima());

TextView texto_inferior_entrada =
(TextView) view.findViewById(R.id.textView_inferior);
if (texto_inferior_entrada != null)

texto_inferior_entrada.setText(((Lista_entrada)
entrada).get_textoDebajo());

ImageView imagen_entrada = (ImageView)
view.findViewById(R.id.imageView_imagen);
if (imagen_entrada != null)

imagen_entrada.setImageResource(((Lista_entrada)
entrada).get_idImagen());
}
}
});

lista.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> pariente,
View view, int posicion, long id) {
Lista_entrada elegido = (Lista_entrada)
pariente.getItemAtPosition(posicion);

CharSequence texto = "Seleccionado: " +
elegido.get_textoDebajo();
Toast toast = Toast.makeText(MainActivity.this, texto,
Toast.LENGTH_LONG);
toast.show();
}
});

}

}
Esperamos que haya sido aclaratorio y para entender muchas cosas sobre cmo se
construye una lista.
Aqu dejo para descargar el proyecto entero: Listado
En respuesta a las preguntas ms comunes de nuestros lectores. Si quieres hacer otra cosa
con los listados, as como si has visto cosas que no has sabido como solucionar; e incluso,
con lo aqu aprendido, como hacer un GridView o un Spinner completamente
personalizados. Te recomiendo que eches una ojeada al artculo que expande los
conocimientos de ListView, se solventan muchas dudas y ensea mucho ms,
en: http://jarroba.com/expansion-listview/
Tambin puede ser muy interesante el artculo sobre programar para diferentes dispositivos
Android con la arquitectura de Fragments, en el que extiendo un poco ms el ejemplo de
listado y aado conceptos avanzados.
Entradas Relacionadas
Activity entender y usar una Actividad

Preparar las herramientas necesarias para programar en Android

Cambiar la clave por defecto de acceso al Men de Configuracin del Router ADSL
(Seguridad Mnima)

Introduccin a Android Studio (Video)




Bibliografa
http://jarroba.com/activity-entender-y-usar-una-actividad/
http://jarroba.com/programar-fragments-fragmentos-en-android/
http://jarroba.com/fragments-fragmentos-en-android/
http://jarroba.com/context-de-android/
http://jarroba.com/intent-pasar-datos-entre-activity-app-android-video/
http://jarroba.com/listview-o-listado-en-android/
http://jarroba.com/fragments-fragmentos-en-android/

También podría gustarte