Including fragments inside other fragments in Android

- Andrés Cruz

En español
Including fragments inside other fragments in Android

The Fragments in Android are a fundamental element in Android that does not allow reusing components in Android with relative ease; we can see the fragments as a piece of interface independent from other fragments and therefore they are highly recommended when we want to develop on Android; What may not be so clear is that within the fragments we can create or embed other fragments, taking this to a second level, and although at first glance it may sound crazy, this can actually solve some very specific problems that we may encounter. ceiling.

Let's suppose that we have some component that is tied to our activity which is in the first instance the one that embeds our fragments, suppose that said component tied to our activity has to be visible in the whole application and that supposedly the application has many screens like screens presented in the image below:

How can one realize by going through these screens that they correspond to multiple fragments within it and depending on the dynamics of the user, they will go from one screen to another at their own pleasure.

Let's name our example component, suppose the component is an audio player:

Reproductor android

Which is a component that we can embed within our activity, which if it is destroyed or recreated, the player will be affected by the same situation, which is not beneficial, since the idea would be for the user to continue listening to the same music without need for it to stop if it decides to go from one screen to another in the application and here is a good opportunity to use the fragments that include other fragments; For example, fragment 1 that we will call Container1Fragment includes other fragments as we can see below:

View v = inflater.inflate(R.layout.fragment_container1, container, false);

FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.flGeneros, new RecyclerViewGenerosFragmentView()).commit();

Bundle bundle = new Bundle();
bundle.putInt("fragment_id", 1);
RecyclerViewArtistasFragmentView recyclerViewArtistasFragmentView = new RecyclerViewArtistasFragmentView();
recyclerViewArtistasFragmentView.setArguments(bundle);
fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.flArtistas, recyclerViewArtistasFragmentView).commit();

bundle = new Bundle();
bundle.putInt("fragment_id", 2);
RecyclerViewArtistasFragmentView recyclerViewArtistasFragmentViewTop = new RecyclerViewArtistasFragmentView();
recyclerViewArtistasFragmentViewTop.setArguments(bundle);
fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.flArtistasTop, recyclerViewArtistasFragmentViewTop).commit();

bundle = new Bundle();
bundle.putInt("id", 13);
bundle.putString("nombre", "");
bundle.putInt("tipo", 3);
bundle.putString("imagen", "");
RecyclerViewCancionesFragmentView recyclerViewCancionesFragmentViewLista = new RecyclerViewCancionesFragmentView();
recyclerViewCancionesFragmentViewLista.setArguments(bundle);
fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.flCancionesLista, recyclerViewCancionesFragmentViewLista).commit();

Let's not worry too much about the Bundle parameters, the goal is to capture the idea which is to embed a fragment inside another fragment; the view for this fragment is as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/llContainer1"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:background="#EEEEEE"
   android:orientation="vertical">

   <TextView
       style="@style/TextViewClasic"
       android:text="@string/tgeneros" />

   <FrameLayout
       android:id="@+id/flGeneros"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical"></FrameLayout>

   <TextView
       style="@style/TextViewClasic"
       android:text="@string/tartistas" />

   <FrameLayout
       android:id="@+id/flArtistas"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical"></FrameLayout>

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="1dp"
       android:background="#CCCCCC"></LinearLayout>

   <TextView
       style="@style/TextViewClasic"
       android:text="@string/ttop" />

   <FrameLayout
       android:id="@+id/flArtistasTop"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical"></FrameLayout>

   <TextView
       style="@style/TextViewClasic"
       android:text="@string/cttop" />

   <FrameLayout
       android:id="@+id/flCancionesLista"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="vertical"></FrameLayout>
</LinearLayout>

As we can see, we have some guide tags and the main thing is the FrameLayout tags to include the fragments shown above from the java code.

Now let's look at the content of one of the fragments that we will include in Container1Fragment:

public class RecyclerViewCancionesFragmentView extends Fragment {
...
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    id = getArguments().getInt("id");
    tipo = getArguments().getInt("tipo");
    imagen = getArguments().getString("imagen");
    nombre = getArguments().getString("nombre");
    descripcion = getArguments().getString("descripcion");
    View v;

        v = inflater.inflate(R.layout.fragment_canciones, container, false);
    rvData = (RecyclerView) v.findViewById(R.id.rvData);
    tvIdentificador = (TextView) v.findViewById(R.id.tvIdentificador);
    init();

    return v;
}
...
}

How can we realize, is it the last fragments or the last level (second level) of the fragment, is the one we really use to interact with the user, specifically (or for this example) we create a list through the RecycleView but you can do anything else like reading a QR code, a webview etc.

In our main activity, which is the one that will include our component (for example, the player) among several things, we do the following:

...
FragmentManager fragmentManager = getSupportFragmentManager();
container1Fragment = new Container1Fragment();
fragmentManager.beginTransaction().replace(R.id.frameLayout, container1Fragment).commit();
...

Although here we can include as many fragments as we want, in our case, in order not to complicate the experiment too much and the general idea of this entry, we only include one, which is our Container1Fragment.

The view or layout of our activity is the following:

<LinearLayout
   android:id="@+id/llParent"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_margin="0dp"
   android:background="#EEEEEE"
   android:orientation="vertical"
   android:padding="0dp">

   <FrameLayout
       android:id="@+id/frameLayout"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_marginBottom="200px"
       android:layout_marginLeft="10dp"
       android:layout_marginRight="10dp"
       android:orientation="vertical"></FrameLayout>

   <LinearLayout
       android:id="@+id/llContainerR"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_gravity="bottom"
       android:orientation="vertical"
       android:textAppearance="@style/TextAppearance.AppCompat.Body1" />

</LinearLayout>

Now, to vary the content of each fragment (first level) or replace some according to the action performed by the user for this experiment, in our case we use the Adapters, that is, our experiment is made up of pure lists and when the user clicks (touch one of the items in the list) an event is executed which updates the entire screen (replaces the content of Container1Fragment for example) shows another fragment or set of embedded fragments or anything else we want depending on our needs; in this example, the click event replaces the content of the main fragment i.e. Container1Fragment:

...
artistaViewHolder.llContainer.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

        Bundle bundle = new Bundle();
        bundle.putInt("id", artista.getArtista_id());
        bundle.putInt("album_id", 0);
        bundle.putInt("tipo", 1);
        bundle.putString("imagen", artista.getImagen_url());
        bundle.putString("nombre", artista.getNombre());

        Container2Fragment container2Fragment = new Container2Fragment();
        container2Fragment.setArguments(bundle);

        FragmentManager fragmentManager = ((FragmentActivity) activity).getSupportFragmentManager();
        fragmentManager.beginTransaction().replace(R.id.frameLayout, container2Fragment).addToBackStack(NULL).commit();
    }
});
...

The rest of the adapter code is the traditional one (initialization of variables and layouts and little else); as we can see, through the click method of the adapter we replace the Container1Fragment with Container2Fragment, which in effect is to replace all the content of a window with other content.

Therefore we only maintain a single activity but we can easily vary their screens with the fragments that the activity embeds and with the fragments embedded by other fragments and in this way we guarantee that our activity will not be destroyed while the user navigates through the application. and neither our component or music player as the case may be.

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.