• Meghan Gill

Fragments in Android with Sample Tutorial


In Android, a fragment is embedded in an activity so that the UI can be separated into modular sections. A fragment takes up a portion or the entire screen and can be reused in other activities. An activity can also have multiple fragments. In essence, a fragment is a sub-activity that gives our UI more flexibility. A fragment is always rooted in an activity and the fragment lifecycle is subject to the host activity's lifecycle.




Fragments with a Bottom Navigation View



In the above example there is one Main Activity whose XML contains a BottomNavigationView. Each fragment fills the space in activity_main.xml above the bottom navigation view. Main Activity controls the fragment transactions i.e. the switching between the Home Fragment, Explore Fragment, Subscriptions Fragment and Library Fragment.


In the above example, one fragment is replacing another. While performing those fragment transactions we can add each fragment to the back stack so that when a user presses the back button the previous fragment is shown.



 

Why do we need fragments?


Before the introduction of fragments we could only show one Activity on the screen at time. We were not able to divide the screen and control different UI sections separately. The Fragment class allows us to split up screens and control those parts separately.


We can use multiple fragments in a single Activity. Fragments have their own events, layouts and complete life cycle. They provide flexibility and remove the limitation of a single Activity on the screen at a time.


 


Key Concepts for Fragments


  • We can add, replace or remove fragments in an activity while the activity is running. For performing these operations we need a layout (FragmentContainerView, Relative Layout, Linear Layout or any other layout) in an xml file and then replace that layout with the required fragment.

  • Fragments have their own layout and their own behavior with their own life cycle callbacks.

  • A fragment can be used in multiple activities.

  • We can also combine multiple fragments in a single activity to build a multi-plane UI.


 


Important Classes for Using Fragments


  1. Fragment - the base class androidx.fragment.app.Fragment. This is the Jetpack Fragment LibraryFragment.

  2. FragmentManager - the class for interacting with a fragment inside of an activity.

  3. FragmentTransaction - the class for performing fragment operations, such as adding a fragment, replacing a fragment or adding it to the back stack.

 

Create a Fragment Class



To create a fragment right click your package name, choose New > Java Class. Name the class OrangeFragment and have it extend Fragment. Use control + O to override the onCreateView lifecycle method.


If you have not done so already, create a Layout Resource File for your fragment. Right click your layout directory, choose New > Layout Resource File. Name the new xml file fragment_orange.


onCreateView creates and inflates the layout for our fragment. As parameters it takes a layoutInflater, a ViewGroup and a Bundle.


package io.meghandev.fragmentpracticetutorial;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class OrangeFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_orange, 
            container, false);
        return view;
    }
}

The LayoutInflator is what we use to turn XML layouts into views. It takes two parameters: 1) A resource ID, 2) A view group. The ViewGroup container (from the activity’s layout) is where our view will be added.


The savedInstanceState parameter is a Bundle that provides data about the previous instance of the Fragment.


The inflate() method has three arguments: first is the resource layout which we want to inflate, second is the ViewGroup to be the parent of the inflated layout. Passing the container is important so the system can apply layout parameters to the root view of the inflated layout, specified by the parent view in which it’s going. The third parameter is a boolean value indicating whether the inflated layout should be attached to the ViewGroup (the second parameter) during inflation.


To properly manage the lifecycle of our fragment we need the third parameter for the inflater to be false. We don't want the view automatically attached to the root container, we want the FragmentTransaction in Main Activity to take care of attaching the fragment.



 

Adding a Fragment to the Activity


When we add a fragment to an activity, we need to specify where in the activity we are adding the fragment. We can do that in one of two ways: 1) Add the fragment in XML or 2) Use a view group as a placeholder and add or remove fragments from that view group in code.



 

Basic Fragment Insertion in the XML


We can put the fragment directly into the XML of the activity's layout (activity_main.xml) by using the <fragment/> tag and specifying the fragment with the name attribute. This is a less flexible approach.


<fragment
    android:layout_width="match_parent"
    android:layout_height="match_parent"
 android:name="io.meghandev.fragmentpracticetutorial.orangefragment"/>



 

Fragment Practice Tutorial with Example






XML: Use a View Group as a FragmentContainer


We want to be able to add or remove fragments so we will be using an empty view group to reserve a spot for fragments in the UI. The selected fragment will take the place of this view group.


We will be using one fragment at a time, so the root view will be FragmentContainerView. We need to access this view group in code, so give it an ID. Name it fragmentContainer.



activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tvColorChoice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Choose your color:"
        android:textSize="22sp"
        android:layout_margin="16dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.google.android.material.button.MaterialButton
        android:id="@+id/btnOrange"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Orange"
        android:layout_marginTop="50dp"
        android:layout_margin="12dp"
        app:layout_constraintTop_toBottomOf="@id/tvColorChoice" />

    <com.google.android.material.button.MaterialButton
        android:id="@+id/btnBlue"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Blue"
        android:layout_marginTop="16dp"
        android:layout_margin="12dp"
        app:layout_constraintTop_toBottomOf="@id/btnOrange"/>


    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragmentContainer"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:layout_marginTop="80dp"
        app:layout_constraintTop_toBottomOf="@id/btnBlue"/>


</androidx.constraintlayout.widget.ConstraintLayout>



MainActivity: Display the Fragment using the Container and Fragment Manager


Fragment Manager is an interface for interacting with our fragments. It helps us keep track of our fragments, lets us manage the back stack of our fragments and gives us access to the fragment transactions A.P.I.


The fragment transactions A.P.I. allows us to add or remove fragments. Fragment transactions are like #SharedPreferences. Changes won't be made permanent until there's a call to commit.



MainActivity.java:

package io.meghandev.fragmentpracticetutorial;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentContainerView;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import android.os.Bundle;
import android.view.View;

import com.google.android.material.button.MaterialButton;

public class MainActivity extends AppCompatActivity {
FragmentContainerView fragmentContainerView;
MaterialButton btnBlue;
MaterialButton btnOrange;

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

        fragmentContainerView = 
            findViewById(R.id.fragmentContainer);
        btnBlue = findViewById(R.id.btnBlue);
        btnOrange = findViewById(R.id.btnOrange);

        btnBlue.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean blueIsClicked = true;
                openFragment(blueIsClicked);
            }
        });

        btnOrange.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean blueIsClicked = false;
                openFragment(blueIsClicked);
            }
        });
    }

    private void openFragment(boolean blueIsClicked) {
        FragmentManager fragmentManager = 
            getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = 
            fragmentManager.beginTransaction();
        if (blueIsClicked == true) {
            fragmentTransaction.replace
            (R.id.fragmentContainer, new BlueFragment());
        } 
        else fragmentTransaction.replace
        (R.id.fragmentContainer, new OrangeFragment());
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
    }
}


Final Source Code for BlueFragment.java:


package io.meghandev.fragmentpracticetutorial;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class BlueFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_blue, 
            container, false);
        return view;
    }
}



Final Source Code for OrangeFragment.java:


package io.meghandev.fragmentpracticetutorial;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class OrangeFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_orange, container, false);
        return view;
    }
}



Final Source Code for fragment_orange.xml:


<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <TextView
        android:id="@+id/tvOrangeLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is the Orange Fragment"
        android:textSize="20sp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_margin="12dp"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:text="ORANGE FRAGMENT"
        android:textSize="20sp"
        android:textColor="@color/white"
        android:textStyle="bold"
        android:gravity="center_horizontal|center_vertical"
        app:layout_constraintTop_toBottomOf="@id/tvRedLabel"
        android:layout_marginTop="12dp"
        android:background="#eab990"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Final Source Code for fragment_blue.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">


    <TextView
        android:id="@+id/tvBlueLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is the Blue Fragment"
        android:textSize="20sp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_margin="12dp"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:text="BLUE FRAGMENT"
        android:textSize="20sp"
        android:textColor="@color/white"
        android:textStyle="bold"
        android:gravity="center_horizontal|center_vertical"
        app:layout_constraintTop_toBottomOf="@id/tvRedLabel"
        android:layout_marginTop="12dp"
        android:background="#90c1ea"/>



</androidx.constraintlayout.widget.ConstraintLayout>


771 views0 comments

Recent Posts

See All