Android Fragment – How to pass data between Fragments in an Activity

Android Fragment – How to pass data between Fragments in an Activity

In this tutorial we are going to learn how to pass data between Fragments in an Activity class. In my previous android tutorial we cover how to use Fragment in android Studio IDE and we went further to learn how we can pass data from a Fragment to its host Activity with Interface.

That post also covers the basic information about android Fragment and when it is important to use a Fragment. I will suggest you read that post before you continue with this tutorial.

Although we learnt how to pass data from Fragment to a host Activity but there are situations when we will like to use two different Fragments in Activity class and we will like the Fragments to pass data to each other.

This is not possible to achieve with a single Activity since Activity class was not design to pass in this way.

In other in ex amplify this, we are going to create two Fragment classes called FirstFragmant.java and SecondFragment.java. We will add the Fragments to our MainActivity class. The FirstFragment will contain different View components with adjustable values.

When the FirstFragment View components are changed and a button is clicked, the changes will be displayed on a TextView component present in the SecondFragment.

Now lets briefly show case what we will like to achieve in this android tutorial. The screen shot below represent the user interface.

android fragment example

If you are using a version of android Studio without support for updated version of appcompat V7 library, you should endeavor to add the compile dependency to your project build.gradle file.

Before we start, the first thing I will do is to list the environment and tools I used in this android tutorial but feel free to use whatever environment or tools you are familiar with.

Windows 7

Android Studio

Sony Xperia ZL

Min SDK 14

Target SDK 19

To create a new android application project, following the steps as stipulated below.

Go to File menu

Click on New menu

Click on Android Application

Enter Project name: AndroidFragmentActivity

Package: com.inducesmile.androidfragmentactivity

Keep other default selections.

Continue to click on next button until Finish button is active, then click on Finish Button

Once you are done with creating your project, make sure you change the package name if you did not use the same package.

The first thing we will do is to create our Fragment class. We will name the class FirstFragment.

1. Right click on your java package

2. In the window fly-out that appeared, hover your mouse on New menu and on the subsequent pop-up, click on the BlankFragment to open a window.

android fragment

3. In the pop-up window, enter the name of the Fragment as FirstFragment and uncheck include Fragment Factory method as shown

android fragment

4. Click the finish button and the Fragment class will be added to our project.

fragment_first.xml

Now open the layout file fragment_first.xml, we are going to add four View components

1. EditText – will be used to get user input

2. SeekBar – will be used to adjust the font size of text

3. LineColorPicker – This is a custom view that afford use the ability to select a particular color from color palette which we will use for our text.

In order to use this view, we will first add the following dependency in our build.gradle file.

dependencies {

compile fileTree(dir: 'libs', include: ['*.jar'])

compile 'com.android.support:appcompat-v7:22.2.0'

compile 'com.github.DASAR:ShiftColorPicker:v0.3'

}

4. Button – will use the event click on the button view to pass data to the host Activity which will in turn update our SecondFragment.

The complete code for our fragment_first.xml is as shown

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="32dp"
    android:background="#574706">

    <EditText
        android:id="@+id/user_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="16dp"
        android:ems="10"
        android:inputType="text">
        <requestFocus />
    </EditText>

    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/user_input"
        android:layout_below="@+id/user_input"
        android:layout_marginTop="16dp" />

    <uz.shift.colorpicker.LineColorPicker
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/picker"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_below="@+id/seekBar"
        android:layout_centerHorizontal="true"
        app:orientation="horizontal" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/picker"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="24dp"
        android:padding="16dp"
        android:elevation="4dp"
        android:text="@string/update_button" />

</RelativeLayout>

FirstFragment.java

In the FirstFragment class, we are going to get all the handles for our View components that we have added in our layout file.

With the help of the LayoutInflater passed as parameter to the onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)  method of the base Fragment class.

The FirstFragment will contain an Interface which must be implemented by the host Activity class. The definition of the Interface is shown below.

public interface OnFragmentInteractionListener {

   public void onFragmentInteraction(String userContent, int size, int colorValue);

}

The onButtonPressed(String userContent, int size, int colorValue)  define in the Fragment class obtains the values that will be passed to the host Activity class. This method is called in the onClick(View v)  method. The method definition is as shown.

public void onButtonPressed(String userContent, int size, int colorValue) {
        if (mListener != null) {
            mListener.onFragmentInteraction(userContent, size, colorValue);
        }
}

The complete code for the FirstFragment class is shown below.

package inducesmile.com.androidfragmentactivity;

import android.app.Activity;
import android.app.Fragment;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.Toast;

import uz.shift.colorpicker.LineColorPicker;
import uz.shift.colorpicker.OnColorChangedListener;


public class FirstFragment extends Fragment {

    private OnFragmentInteractionListener mListener;
    private EditText userInput;
    private LineColorPicker colorPicker;
    private static int seekBarValue = 10;
    private static int mColor;
    private String userData;

    public FirstFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_first, container, false);

        userInput = (EditText)view.findViewById(R.id.user_input);
        SeekBar seekBar = (SeekBar)view.findViewById(R.id.seekBar);
        colorPicker =(LineColorPicker)view.findViewById(R.id.picker);

        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                seekBarValue = progress;
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
        });

        colorPicker.setColors(new int[] {Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW});
        colorPicker.setSelectedColor(Color.RED);
        colorPicker.setOnColorChangedListener(new OnColorChangedListener() {
            @Override
            public void onColorChanged(int c) {
                Log.d("TAG ", "Selectede color " + Integer.toHexString(c));
            }
        });

        Button update = (Button)view.findViewById(R.id.button);
        update.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mColor = colorPicker.getColor();
                if(userInput.getText().toString().equals("")){
                    Toast.makeText(getActivity(), "User input value must be filled", Toast.LENGTH_LONG).show();
                    return;
                }
                userData = userInput.getText().toString();
                onButtonPressed(userData, seekBarValue, mColor);
            }
        });
        return view;
    }

    public void onButtonPressed(String userContent, int size, int colorValue) {
        if (mListener != null) {
            mListener.onFragmentInteraction(userContent, size, colorValue);
        }
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    public interface OnFragmentInteractionListener {
        public void onFragmentInteraction(String userContent, int size, int colorValue);
    }

}

fragment_second.xml

Now that we have finished with the FirstFragment class, we will proceed to the SecondFragment class. Following the same process we used to create our FirstFragment class but in this case, we will change the Fragment name to SecondFragment.

Once you are done, open the SecondFragment layout file called fragment_second.xml, go to the design view of the Android Studio and drag and drop a TextView in the layout file. You can also copy and paste the complete code for the layout file.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text_update"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:textStyle="bold"
        android:layout_marginTop="32dp" />

</RelativeLayout>

SecondFragment.java

Lets open the SecondFragment.java file, We are going to get the handle for our TextView component.

We will go ahead to create a public method that updates the text property of the TextView control. The method signature is as shown

public void updateTextField(String newText, int size, int color){
        updateText.setText(newText);
        updateText.setTextSize(size);
        updateText.setTextColor(color);
}

The complete code for the SecondFragment class is below

package inducesmile.com.androidfragmentactivity;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class SecondFragment extends Fragment {

    private TextView updateText;

    public SecondFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_second, container, false);
        updateText = (TextView)view.findViewById(R.id.text_update);
        return view;
    }

    public void updateTextField(String newText, int size, int color){
        updateText.setText(newText);
        updateText.setTextSize(size);
        updateText.setTextColor(color);
    }
}

activity_main.xml

Open the activity_main.xml, delete the TextView and change the root ViewGroup contain to RelativeLayout.

Then, switch to the design view of the Android Studio if you are not using it already. In the custom section, click on the <fragment> menu to open is pop-up window.

Fragment example

Select the FirstFragment and click Ok. Drag and drop the FirstFragment where you want it to appear in the layout.

Follow the same process to add the SecondFragment below the FirstFragment in the Let out. Remember to select the Fragment class that will be associated with each Fragment layout property.

This is the code complete for the activity_main.xml layout file.

<RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:background="#574706"
    tools:context=".MainActivity">

    <fragment
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:name="inducesmile.com.androidfragmentactivity.FirstFragment"
        android:id="@+id/fragment"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        tools:layout="@layout/fragment_first" />

    <fragment
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:name="inducesmile.com.androidfragmentactivity.SecondFragment"
        android:id="@+id/fragment2"
        android:layout_below="@+id/fragment"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="41dp"
        tools:layout="@layout/fragment_second" />

</RelativeLayout>

MainActivity.java

Finally, we are going to look into our MainActivity.java file. We have to implement our interface.

public class MainActivity extends AppCompatActivity implements FirstFragment.OnFragmentInteractionListener {

By declare that we will implement the OnFragmentInteractionListener, it applies that we must also implement the onFragmentInteraction(String userContent, int size, int colorValue)  which passes three different values as parameter.

In the method, we will use the values of the parameters to update the TextView in the SecondFragment class as shown in the code snippet.

package inducesmile.com.androidfragmentactivity;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;


public class MainActivity extends AppCompatActivity implements FirstFragment.OnFragmentInteractionListener {

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

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onFragmentInteraction(String userContent, int size, int colorValue) {
        SecondFragment secondFragment = (SecondFragment)getSupportFragmentManager().findFragmentById(R.id.fragment2);
        secondFragment.updateTextField(userContent, size, colorValue);
    }
}

Now, when you run your application you will see the interface that looks similar to the sample that was shown earlier on.

You can download the code for this tutorial below. If you are having hard time downloading the tutorials, kindly contact me.

Remember to subscribe with your email so that you will be among the first to receive our new post once it is published

OTHER INTERESTING POSTS:

Add a Comment