Fragmento Fragment

01 – Entender el Fragment

Introducción al curso

Este curso requiere que tengas conocimientos básicos de Android.

Sin esa base, será difícil seguir adelante.

Fragment se traduce como «fragmento» o «pedazo».

En realidad, «fragmento» es lo más correcto.

Es un fragmento de interfaz de usuario incrustado en una Activity.

Permite que las aplicaciones aprovechen mejor el espacio de las pantallas grandes.

Por eso es ideal para tablets.

Se parece mucho a una Activity: tiene su propio layout y su propio ciclo de vida.

Puedes pensar en él como una Activity en miniatura.

Cuando desarrollamos una aplicación de noticias,

en una pantalla de móvil, podríamos diseñarlo así:

una Activity de lista, y al pulsar se abre una Activity de detalle de la noticia.

Pero en una tablet, hacer lo mismo dejaría grandes espacios en blanco, lo cual no es bueno.

Un diseño mejor es dividir la lista y el detalle en dos fragmentos dentro de una misma Activity.

Crear un emulador de tablet

Para probar mejor nuestra app en tablet, vamos a crear un emulador de tablet.

02 – Primer ejemplo con Fragment

Añadir dos fragmentos en una Activity y que compartan el espacio por igual.

Crea un nuevo proyecto llamado FragmentFirst.

Añade dos layouts: uno para el fragmento de la izquierda

newlist.xml

y otro para el fragmento de la derecha, newdetail.xml.

Fragmento izquierdo

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/buttondialog"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Guerra comercial entre China y EE. UU. 2018" />
</LinearLayout>Lenguaje del código: HTML, XML (xml)

Fragmento derecho

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#0ddb97"
    >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Contenido de la noticia contenido de la noticia" />
</LinearLayout>Lenguaje del código: HTML, XML (xml)

Añadir la clase del fragmento

Añade un NewListFragment.

Hereda de android.support.v4.app.Fragment.

Luego sobrescribe el método onCreateView para que este fragmento use el xml newlist.

public class NewListFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.newlist,container,false);
        return view;
    }
}Lenguaje del código: PHP (php)

Añade el fragmento de detalle de noticia de la misma forma.

NewDetailFragment también hereda de

android.support.v4.app.Fragment.

public class NewDetailFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.newdetail,container,false);
        return view;
    }
}Lenguaje del código: PHP (php)

Llamar a los fragmentos en la vista de la actividad principal

Usa el atributo android:name=»com.foxdevelop.» para configurar qué fragmento usar.

Al añadir una vista de fragmento en el layout principal, el id es obligatorio.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment
        android:id="@+id/newlist_fragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:name="com.foxdevelop.www.fragmentfirst.NewListFragment"
        />
    <fragment
        android:id="@+id/newdetail_fragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3"
        android:name="com.foxdevelop.www.fragmentfirst.NewDetailFragment"
        />
</LinearLayout>Lenguaje del código: HTML, XML (xml)

03 – Añadir fragmentos dinámicamente

La verdadera potencia de los fragmentos es que se pueden añadir dinámicamente a una Activity mientras la app se está ejecutando.

Añadiendo fragmentos dinámicamente según la situación, podemos crear interfaces mucho más variadas.

Por ejemplo, en nuestra app de noticias, algunos artículos son de imagen, otros de texto y otros de vídeo. Según el tipo de noticia, podemos cargar diferentes layouts de fragmentos.

Vamos a añadir una vista new_picture.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/birdsee"
        />
</LinearLayout>Lenguaje del código: HTML, XML (xml)

Para distinguirlo, simplemente muestra una imagen.

Añadir la clase de fragmento para imágenes

public class NewImageFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.new_picture,container,false);
        return view;
    }
}Lenguaje del código: PHP (php)

Usar FrameLayout en la vista principal

Aquí usamos un FrameLayout.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment
        android:id="@+id/newlist_fragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:name="com.foxdevelop.www.fragmentfirst.NewListFragment"
        />

    <FrameLayout
        android:id="@+id/framelayout"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3"
        ></FrameLayout>
</LinearLayout>Lenguaje del código: HTML, XML (xml)

Añadir dos botones a la izquierda

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/buttondialog"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Guerra comercial entre China y EE. UU. 2018" />
    <Button
        android:id="@+id/buttonpicture"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Noticia de imagen" />
</LinearLayout>Lenguaje del código: HTML, XML (xml)

Añadir eventos a los botones en la actividad principal

Configurando eventos de clic en los botones, podemos cargar dinámicamente diferentes fragmentos según el botón pulsado.

package com.foxdevelop.www.fragmentfirst;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Vincular eventos a los dos botones
        Button b1 = (Button)findViewById(R.id.buttonarticle);
        b1.setOnClickListener(this);
        Button b2 = (Button)findViewById(R.id.buttonpicture);
        b1.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        // Configurar diferentes fragmentos según el botón
        switch (view.getId())
        {
            case R.id.buttonarticle:
                setFragement(new NewDetailFragment());
                break;
            case R.id.buttonpicture:
                setFragement(new NewImageFragment());
                break;
            default:
                break;
        }
    }

    // Este método configura el fragmento para el FrameLayout
    public void setFragement(Fragment fragement) {
        FragmentManager fragementManager = getSupportFragmentManager();
        // Iniciar la transacción
        android.support.v4.app.FragmentTransaction fragmentTransaction = fragementManager.beginTransaction();
        fragmentTransaction.replace(R.id.framelayout,fragement);// Configura el FrameLayout para usar el fragmento pasado
        fragmentTransaction.commit();
    }
}Lenguaje del código: JavaScript (javascript)

04 – Usar la pila de retroceso (back stack) con fragmentos

En el curso básico ya explicamos qué es la pila de retroceso.

En el ejemplo anterior, al pulsar el botón back, la app sale directamente de la actividad principal y termina el programa. Pero ese no es el comportamiento que queremos; queremos que al pulsar back se vuelva al fragmento anterior.

Hacer que los fragmentos soporten la pila de retroceso es en realidad muy sencillo.

Solo hay que añadir la transacción a la pila de retroceso.

// Este método configura el fragmento para el FrameLayout
public void setFragement(Fragment fragement) {
    FragmentManager fragementManager = getSupportFragmentManager();
    // Iniciar la transacción
    android.support.v4.app.FragmentTransaction fragmentTransaction = fragementManager.beginTransaction();
    fragmentTransaction.replace(R.id.framelayout,fragement);// Configura el FrameLayout para usar el fragmento pasado
    fragmentTransaction.addToBackStack(null);// Añade la transacción a la pila de retroceso
    fragmentTransaction.commit();
}Lenguaje del código: JavaScript (javascript)

05 – Comunicación entre Fragment y Activity

Los fragmentos están incrustados en las actividades, pero en realidad su relación no es tan estrecha.

Nuestro fragmento y nuestra actividad existen en realidad como clases independientes.

No hay una forma directa para que se comuniquen entre sí.

Para facilitar la comunicación,

FragmentManager proporciona un método similar a findViewById, que sirve para obtener una instancia del fragmento desde el layout.

getFragmentManager android.support.v4.app.Fragment

necesita hacerse cast. Esto no se menciona en el libro.

Si has importado el paquete android.support.v4.app.Fragment (es decir, el paquete v4)

import android.support.v4.app.Fragment;

entonces, al obtener el FragmentManager, deberías usar

FragmentManager fm = getSupportFragmentManager();

¡El fragmento correspondiente también debe importar el paquete correcto!

// Obtener la instancia del fragmento en el método onCreate de la actividad
NewListFragment newListFragment = (NewListFragment)getSupportFragmentManager().findFragmentById(R.id.newlist_fragment);
Toast.makeText(this, newListFragment.getId()+"xxxx",Toast.LENGTH_LONG).show();Lenguaje del código: JavaScript (javascript)

Obtener la Activity desde el fragmento

// Obtener la Activity desde el fragmento
MainActivity mainActivity = (MainActivity) getActivity();
Toast.makeText(getContext(), mainActivity.getTitle(),Toast.LENGTH_LONG).show();Lenguaje del código: JavaScript (javascript)

Puedes llamar al método getActivity().

06 – Ciclo de vida del Fragment

El ciclo de vida del fragment es básicamente el mismo que el de la Activity.

Los fragmentos también tienen cuatro estados.

En ejecución, Pausado, Detenido, Destruido.

1. Estado en ejecución: el fragmento es visible y la actividad a la que pertenece está en ejecución, por lo que el fragmento también está activo.

2. Estado pausado

Cuando otra actividad que no ocupa toda la pantalla se añade a la cima de la pila, el fragmento visible que gestiona pasa al estado pausado.

3. Estado detenido

Cuando una actividad entra en estado detenido, sus fragmentos relacionados también entran en estado detenido. O bien, si se usa el método remove o replace de FragmentTransaction para quitar un fragmento de una actividad, y se llama a addToBackStack antes de confirmar la transacción, también entrará en estado detenido.

En resumen, un fragmento en estado detenido no es visible para el usuario y puede ser reciclado por el sistema en cualquier momento.

4. Estado destruido

Los fragmentos siempre dependen de las actividades, por lo que cuando una actividad se destruye, sus fragmentos relacionados también entran en estado destruido. O bien, si se usa remove o replace para quitar un fragmento sin llamar a addToBackStack antes de confirmar, también entrará en estado destruido.

Al igual que las actividades, Fragment también proporciona una serie de métodos de callback que cubren cada etapa del ciclo de vida. Casi todo lo que tiene una Activity, también lo tiene un Fragment.

Al mismo tiempo, Fragment también proporciona algunos métodos de callback adicionales.

Fragmento Fragment

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *