Android Fragments – An Introductory Tutorial

Fragments are a way to make your Android application modular and more flexible. This is a short and, hopefully clear, introductory tutorial on how to implement fragment functionality in your Android application.

What are fragments?

From the official Android documentation:

A Fragment represents a behavior or a portion of user interface in an Activity. You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities.

Basically, they behave like “mini activities” if you want. They have almost all the capabilities of a standard activity, they follow a similar lifecycle and they have their own XML layouts. You can think of an activity as a container of fragments. Most of app the functionality can be transferred inside fragments, which can communicate with each other and with the parent activity.

What can fragments be used for?

Historically, before Android 3.0, you had to use multiple activities to implement different views and functionality in the app, and you had to use intents to jump between different activities.

Fragments were first introduced in Android 3.0 Honeycomb, that weird Android version that specifically targeted tablets. Using fragments, you could have multiple elements in a view that could communicate with each other. Take the case of an email application, for example: while in landscape mode, you could have one fragment on the left showing the list of emails, and another fragment on the right showing the content of the selected email.

Take this a step further and you can also use the concept to show or hide fragments depending on the orientation of the device or on its screen size. Take this yet another step further, and you can start building flexible apps, hiding and showing views as needed, all inside a single activity.

Tutorial

We are going to build a basic Android application from scratch that shows how to add a fragment to an activity at runtime, and how to replace this first fragment with a second fragment. We are going to add a button to switch from one fragment to the other so, at the end of the tutorial, you will have a working example of an app implementing fragments and the functionality to replace one fragment with another.

Let’s get started.

Create an empty project

Launch Android Studio and start a new project. Give the application a name and a domain and choose where to save the project.

Create New Project

Give your app a name, a domain and select where you want to save your project.

Click on Next and select only Phone and tablet in the next window. I chose API 14 as the minimum SDK version but feel free to select another option if you wish.

Form factor and API version

Select the device you want the app to run on and the minimum supported SDK version

Click on Next and select Empty Activity.

Activity type

Select an activity type. Empty Activity will do just fine for this tutorial.

Click on Next and give a name to this activity. You can leave everything untouched here.

Customize the activity

Choose a name for the activity and its layout.

Click on Finish to create the project. Android Studio will build your project and bring you to MainActivity.java once done.

Create a fragment

On the left column, expand app > java and right-click on com.yourdomain.fragmenttutorial to bring up the options menu. Here, select New > Fragment > Fragment (Blank).

Create fragment

Create a new empty fragment

We can now give the fragment and its layout a name, similar to what we would do if we were creating a new activity instead. Give the fragment the name BlankFragment1 and the layout name should automatically be updated to fragment_blank_fragment1. Also tick all the checkboxes.

Customize the fragment

The fragment customization screen

Click on Finish when done. Once the Gradle sync is complete, go ahead and create a second fragment following the same method. Call this fragment BlankFragment2.

Prepare the activity layout

We now have all the files we need. Let’s edit the main activity’s layout so that it will include the content of our fragments.

In order for this to work, the main activity should include a container section where the fragments will end up. We will use a FrameLayout for this. In the left column of Android Studio, expand the res folder and then the layout folder. Open activity_main.xml and paste this:

<?xml version="1.0" encoding="utf-8"?>
<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: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="com.danielpellarini.fragmenttest.MainActivity"
    android:orientation="vertical">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Replace fragment"
        android:onClick="replaceFragment" />

    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </FrameLayout>
</LinearLayout>

Very basic layout, only including a button (which we will use to replace the current fragment with the other) and a placeholder for the fragment content.

Create the fragment layouts

Now open the strings.xml file under res > values and paste two different messages which we are going to assign to the two fragments so we can make sure that the app is really switching between them:

<resources>
    <string name="app_name">FragmentTutorial</string>

    <string name="hello_blank_fragment1">Hello blank fragment 1</string>
    <string name="hello_blank_fragment2">Hello blank fragment 2</string>
</resources>

Now assign these strings to the relevant fragment. For example, in res > layout > fragment_blank_fragment1.xml:

<FrameLayout 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"
    tools:context="com.yourdomain.fragmenttutorial.BlankFragment1">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/hello_blank_fragment1" />

</FrameLayout>

Do the same for fragment_blank_fragment2.xml, using the other string.

Add a fragment to an activity at runtime

We now have to edit the main activity’s onCreate method to add a fragment to its container at runtime. This is the code for the method:

public class MainActivity extends AppCompatActivity {

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

        if (findViewById(R.id.fragment_container) != null) {
            if (savedInstanceState != null) {
                return;
            }
            BlankFragment1 blankFragment1 = new BlankFragment1();
            getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, blankFragment1).commit();
        }
    }
}

First, we look for the fragment_container element in the XML. If we have one (and we do), we check if we have anything that we can restore in the activity (which we don’t at the moment), we create an instance of BlankFragment1 ad use getSupportFragmentManager() to add it inside the fragment_container.

If you try to run the app just now, the app will crash and Logcat would show the error message “com.yourdomain.fragmenttutorial.MainActivity@41ff3e7 must implement OnFragmentInteractionListener”. Have your MainActivity class implement it then (the method can be left blank, things will work anyway):

public class MainActivity extends AppCompatActivity implements BlankFragment1.OnFragmentInteractionListener {

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

        if (findViewById(R.id.fragment_container) != null) {
            if (savedInstanceState != null) {
                return;
            }
            BlankFragment1 blankFragment1 = new BlankFragment1();
            getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, blankFragment1).commit();
        }
    }

    @Override
    public void onFragmentInteraction(Uri uri) {
        //
    }
}

Now you can run the app. If you are using an emulator, you should see this:

Emulator fragment 1

The fragment was added to the activity at runtime

Replace the fragment with the second one

On our button we have defined an onClick event that should call the replaceFragment method. We just need to implement this method in our main activity:

public void replaceFragment(View view) {
    BlankFragment2 blankFragment2 = new BlankFragment2();
    getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,blankFragment2).addToBackStack(null).commit();
}

Similar to what we did for BlankFragment1, we create a new instance of BlankFragment2 and we call getSupportFragmentManager(), only this time we use the replace method rather than the add method, and we use addToBackStack(null) to be able to get back to the first fragment. Essentially, if a user clicks on the replace button and then uses the back button on the device, the first fragment will be shown again.

Make sure you implement the OnFragmentInteractionListener for BlankFragment2, like you did with fragment 1. There is no need to implement the method another time as you have already done it in the previous step.

This is the final complete code for MainActivity.java:

public class MainActivity extends AppCompatActivity implements BlankFragment1.OnFragmentInteractionListener, BlankFragment2.OnFragmentInteractionListener {

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

        if (findViewById(R.id.fragment_container) != null) {
            if (savedInstanceState != null) {
                return;
            }
            BlankFragment1 blankFragment1 = new BlankFragment1();
            getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, blankFragment1).commit();
        }
    }

    @Override
    public void onFragmentInteraction(Uri uri) {
        //
    }

    public void replaceFragment(View view) {
        BlankFragment2 blankFragment2 = new BlankFragment2();
        getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,blankFragment2).addToBackStack(null).commit();
    }
}

Remember that you might have to import quite a few packages if you copy and paste the code in this post, but Android Studio will prompt you to do so if it sees that you are missing any dependencies.

Now run the app again and click on the Replace Fragment button. If everything went well, you should see the second fragment that the place of the first one:

Emulator fragment 2

After clicking on the button, fragment 2 will take fragment 1’s place

If you click on the device’s back button, you will see the first fragment again.

There you go, you now have a working example of an Android activity that makes use of multiple fragments. Granted, this is just the basics, but hopefully this should get you started and allow you to extend your app’s functionality.

If you have any questions or feedback, please feel free to drop a comment down below.

2 Comments

  1. I use 3 fragments in my main Activity i add onFragmentInteraction in my activity 1st fragment run well but next 2 cannot open it show must implement onFragmentInteraction listner error…what can i do pls help me

    • Your MainActivity must implement OnFragmentInteractionListener for each of your 3 fragments, not just for the first one. When you declare your MainActivity class, make sure you implement it for each fragment:

      implements fragment1.OnFragmentInteractionListener, fragment2.OnFragmentInteractionListener, fragment3.OnFragmentInteractionListener

Leave a Reply

© 2017 Daniel's TechBlog

Theme by Anders NorénUp ↑

%d bloggers like this: