Comunicación entre Fragments en Android

Buenos días, en esta entrada vamos a ver algo mas sobre Fragments, en este caso como pueden comunicarse entre ellos, pero de una manera muy fácil.


Los Fragments son pequeñas actividades que pueden ser ejecutadas en una misma Activity a la vez, y tienen su propio ciclo de vida.

Como bien he dicho anteriormente es una forma de hacer el proceso de comunicación, pero nos puede servir de guia para aplicaciones u operaciones mas complejas, que ya veremos en otra entrada mas a fondo.

Con esta introducción breve, podemos empezar con el ejemplo:

  • Crear Proyecto Android

    En este punto no debe de ser nada complicado este punto, pero solo tenemos que dirigirnos a File -> New -> Android Application Project, o si no nos sale en la lista, vamos a Other y allí podemos filtrar mediante la caja de texto si introducimos Android.

    Seguimos los pasos para darle nombre a nuestro proyecto, en mi caso lo he llamado “ComunicacionFragments”, y los siguientes pasos seguimos hacia delante, cuando nos aparezca la pantalla de poner nombre a nuestra Activity principal, le ponemos un nombre, en mi caso la he llamado ComunicacionFragments (como el proyecto), y su archivo de layout.xml se llamará “activity_comunicacion_fragments.xml”.

    Cuando hayamos terminado de crear nuestro proyecto, podemos ir al siguiente paso.

  • Creación de Fragments

    Vamos a crear los 2 Fragment que vamos a usar, los cuales serán casi idénticos a los creados en entradas anteriors sobre Fragments, aunque vamos a verlo igualmente.

    • Fragment1.java

      Uno de nuestros Fragment se llamará Fragment1.java, el cual vamos a hacer creando una nueva clase java en nuestro package, y esta clase heredará de la superclase Fragment.

      Una vez tengamos creado nuestro Fragment1.java, vamos a crear un nuevo archivo xml en la carpeta res/layout, el cual contendrá la interfaz gráfica del Fragment, en mi caso, lo he llamado fragment1.xml:

      				<?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:orientation="vertical"
      				    android:background="#00FF00" >
      				
      				    <TextView
      				        android:id="@+id/lblFragment1"
      				        android:layout_width="fill_parent"
      				        android:layout_height="wrap_content"
      				        android:text="Este es el Fragment #1"
      				        android:textColor="#000000"
      				        android:textSize="25sp" />
      				
      				</LinearLayout>
      				

      Hemos definido un TextView con un texto definido, el cual nos informa que estamos en el Fragment#1, y en el contenedor principal, el LinearLayout, hemos puesto un color chillón para diferenciarlo mas tarde del otro Fragment.

      Respecto al código Java, es el siguiente:

      				public class Fragment1 extends Fragment {
      
      					@Override
      					public View onCreateView(LayoutInflater inflater, ViewGroup container,
      							Bundle savedInstanceState) {
      						// TODO Auto-generated method stub
      						return inflater.inflate(R.layout.fragment1, container, false);
      					}
      				
      				}
      				

      No es para nada algo nuevo, en el método onCreateView retornamos un View que contiene la interfaz del fragment.

    • Fragment2.java

      Nuestro segundo Fragment se llamará Fragment2.java, el cual creamos creando una nueva clase Java en nustro package y el cual debe heredar de la superclase Fragment.

      Con nuestra clase creada, vamos a crear inmediatamente un archivo xml en la carpeta res/layout, el cual definirá el aspecto que tendrá el Fragment, y en mi caso, lo he llamado fragment2.xml:

      				<?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:orientation="vertical"
      				    android:background="#FFFE00" >
      				
      				    <TextView
      				        android:id="@+id/lblFragment2"
      				        android:layout_width="fill_parent"
      				        android:layout_height="wrap_content"
      				        android:text="Este es el Fragment #2"
      				        android:textColor="#000000"
      				        android:textSize="25sp" />
      				    
      				    <Button 
      				        android:id="@+id/btnObtenerTexto"
      				        android:layout_width="fill_parent"
      				        android:layout_height="wrap_content"
      				        android:text="Obtener texto de Fragment #1"
      				        android:textColor="#000000" 
      				        android:onClick="onClick"/>
      				
      				</LinearLayout>
      				

      Como podemos ver examinando su código, en este caso tenemos un contenedor LinearLayout, el cual tiene como fondo un amarillo muy llamativo, y luego tenemos un TextView el cual nos indica que estamos en el Fragment#2. A continuación, un Button que usaremos para obtener un texto desde el Fragment#1.

      Respecto al código java del Fragment2.java, tiene algo mas de complejidad que el Fragment1:

      				public class Fragment2 extends Fragment {
      
      					@Override
      					public View onCreateView(LayoutInflater inflater, ViewGroup container,
      							Bundle savedInstanceState) {
      						// TODO Auto-generated method stub
      						return inflater.inflate(R.layout.fragment2, container, false);
      					}
      				
      					@Override
      					public void onStart() {
      						// TODO Auto-generated method stub
      						super.onStart();
      						Button btnGetText = (Button) getActivity().findViewById(
      								R.id.btnObtenerTexto);
      						btnGetText.setOnClickListener(new OnClickListener() {
      				
      							@Override
      							public void onClick(View arg0) {
      								// TODO Auto-generated method stub
      								TextView lbl = (TextView) getActivity().findViewById(
      										R.id.lblFragment1);
      								Toast.makeText(getActivity(), lbl.getText(), Toast.LENGTH_SHORT)
      										.show();
      							}
      				
      						});
      					}
      				
      				}
      				

      Tenemos algo más de complejidad respecto al Fragment1, por tanto vamos a analizarlo:

      • onStart

        						@Override
        						public void onStart() {
        							// TODO Auto-generated method stub
        							super.onStart();
        							Button btnGetText = (Button) getActivity().findViewById(
        									R.id.btnObtenerTexto);
        							btnGetText.setOnClickListener(new OnClickListener() {
        					
        								@Override
        								public void onClick(View arg0) {
        									// TODO Auto-generated method stub
        									TextView lbl = (TextView) getActivity().findViewById(
        											R.id.lblFragment1);
        									Toast.makeText(getActivity(), lbl.getText(), Toast.LENGTH_SHORT)
        											.show();
        								}
        					
        							});
        						}
        						

        Este método se ejecuta una vez que el Fragment ha pasado por el método onCreateView. Aquí lo que hemos hecho es crear una variable de referencia al Button, el cual hemos buscado su id mediante el método getActivity(), y luego con el método findViewById establecemos su id.

        Después le asignamos un onClickListener al Button, y dentro del método onClick instanciamos el TextView del Fragment1, el cual localizamos mediante el método getActivity().findViewById(), con el cual obtenemos el Fragment1 que está en la pantalla y con el findViewById establecemos el id que deseamos, en este caso, el TextView del Fragment1. Luego, creamos un objeto Toast que mostrará el texto que tiene el TextView de Fragment1.

  • ComunicacionFragment.java

    En nuestra Activity principal llamada ComunicacionFragment.java, no tenemos que añadir demasiado, vemos a continuación el contenido de activity_comunicacion_fragments.xml:

    		<LinearLayout 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:orientation="horizontal"
    		    tools:context=".ComunicacionFragments" >
    		
    		    <fragment
    		        android:id="@+id/fragment1"
    		        android:name="sekth.droid.comunicacionfragments.Fragment1"
    		        android:layout_width="0dp"
    		        android:layout_height="fill_parent"
    		        android:layout_weight="1" />
    		
    		    <fragment
    		        android:id="@+id/fragment2"
    		        android:name="sekth.droid.comunicacionfragments.Fragment2"
    		        android:layout_width="0dp"
    		        android:layout_height="fill_parent"
    		        android:layout_weight="1" />
    		
    		</LinearLayout>
    		

    Volvemos a tener un contenedor LinearLayout, con orientación horizontal, y 2 fragments dentro de el. Cada fragment rellenará la mitad de la pantalla que esté disponible, sin importar sus dimensiones. Por tanto, antes de ejecutar la aplicación, podemos ver que el Fragment#1 estará a la izquierda, y el Fragment#2 estará a la derecha.

    Respecto al código java de la clase ComunicacionFragment.java, tenemos lo siguiente:

    		public class ComunicacionFragments extends FragmentActivity {
    
    			@Override
    			protected void onCreate(Bundle savedInstanceState) {
    				super.onCreate(savedInstanceState);
    				setContentView(R.layout.activity_comunicacion_fragments);
    			}
    		
    		}
    		

    Como vemos, nuestra clase puede heredar de FragmentActivity en vez de Activity. En mi caso esta aplicación funcionará tanto en dispositivos con versiones de Android anteriores a 3.0 (API 11) como en las siguientes. Es una manera de poder abarcar mas dispositivos, ya que debido al problema de la Fragmentación en Android, tenemos millones de dispositivos, pero se suelen dividir en 4 o 5 versiones que son cruciales. Si por otro lado quisieramos solo desarrollar para versiones de Android con la API 11 en adelante, nuestra Activity no tiene que heredar de FragmentActivity, sino de Activity, como normlamente ha sido.

Ahora nuestra aplicación puede ser ejecutada, y veremos como efectivamente se disponen los 2 Fragment en la pantalla, y lo que pasa si pulsamos el Button del Fragment#2.

Foto con Dispositivo en Portrait:

ComunicacionFragmentPortrait

Foto con Dispositivo en Landscape:

ComunicacionFragmentLandscape

A continuación un vídeo de la aplicación en ejecución:


Hasta aquí este pequeño ejemplo, aunque como ya comenté antes, es un modo de comunicación entre Fragments no demasiado complicado, pero también hay otros métodos para lograr esto, como implementar la Interface OnFragmentClickListener, por ejemplo, el cual se implementa en la Activity que soporta los Fragment, y luego mediante un método en cada Fragment. Lo importante ha sido ver que nuestros Fragments pueden comunicarse entre ellas lo que nos dá un enfoque importante sobre las aplicaciones que queramos hacer y que implementen Fragments.

El código de este ejemplo puedes bajarlo de aquí.

Sin más, cualquier aporte o corrección son beinvenidos!.

Saludos!!!

  • Lugh

    Hola que tal, tengo algunas dudas con los fragment y fragmentactivity. Estoy haciendo una aplicacion que cuando abre te muestra un listado echo con listfragment esto esta todo ok, cuando seleccionas una opcion te tiene que mostrar otro fragment el cual tiene 1 textviev 2 button, cuando se preciona el button “Aceptar” se debe mostrar otro fragment y pasarle datos a dicho fragment.
    No se si fue lo suficientemente claro, pero me podras iluminar un poco el caminio.

    • Buenas Lugh,

      Lo primero, que método estás usando?, lo denominado como “Fragment Dinámicos” o con “Fragment Estáticos”?.

      Los dinámicos son aquellos que gestionas con el “FragmentTransaction” y los estáticos aquellos que están definidos en el xml como:

      <fragment ... />
      

      Cierto es que el método que he aplicado en esta entrada no es el más adecuado, y estoy en proceso de crear otro mediante uso de una Interface, que es el que mas te interesa, igualmente podemos ver como lo puedes hacer 🙂

  • Hola que tal… Soy nuevo en esto de Android y he estado peleando mucho durante estos días con los fragments xD Quisiera saber si es posible que se pueda abrir un fragment con un parámetro enviado desde el actual, algo así como los parametros GET en HTML.