In this tutorial, we’ll be developing an application that contains TabLayout, ViewPager and Fragments. We’ll implement a functionality that passes data from one Fragment to the other fragment.
Intents are only usable for sending data on an Activity level. To pass data between fragments we need to create our own interfaces. The flow to send a String data from one Fragment to another is shown below. Let’s get started with the implementation of the above flow.
The xml layout for the MainActivity.java class is given below.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.journaldev.passingdatabetweenfragments.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
style="@style/MyStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"
app:tabMode="fixed" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
The styles for the TabLayout and ToolBar are defined in the styles.xml file as shown below.
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
<style name="MyStyle" parent="Widget.Design.TabLayout">
<item name="tabIndicatorColor">#FFFF</item>
<item name="tabIndicatorHeight">5dp</item>
<item name="tabPaddingStart">8dp</item>
<item name="tabPaddingEnd">8dp</item>
</style>
</resources>
The ViewPagerAdapter.java is where the Fragments are initialised. The code is given below.
public class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
if (position == 0) {
fragment = new FragmentOne();
} else if (position == 1) {
fragment = new FragmentTwo();
}
return fragment;
}
@Override
public int getCount() {
return 2;
}
@Override
public CharSequence getPageTitle(int position) {
String title = null;
if (position == 0) {
title = "Tab-1";
} else if (position == 1) {
title = "Tab-2";
}
return title;
}
}
FragmentOne would be sending the data entered in EditText to FragmentTwo. The xml layout for fragment_one.xml is given below.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/inMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/btnPassData"
android:layout_margin="16dp"
android:hint="Enter here" />
<Button
android:id="@+id/btnPassData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="PASS DATA TO FRAGMENT TWO" />
</RelativeLayout>
</ScrollView>
The xml layout for fragment_two.xml is given below.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/txtData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:layout_centerInParent="true"
android:text="No data received" />
</RelativeLayout>
The code for FragmentOne.java class is given below.
package com.journaldev.passingdatabetweenfragments;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
public class FragmentOne extends Fragment {
SendMessage SM;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(
R.layout.fragment_one, container, false);
return rootView;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Button btnPassData = (Button) view.findViewById(R.id.btnPassData);
final EditText inData = (EditText) view.findViewById(R.id.inMessage);
btnPassData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SM.sendData(inData.getText().toString().trim());
}
});
}
interface SendMessage {
void sendData(String message);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
SM = (SendMessage) getActivity();
} catch (ClassCastException e) {
throw new ClassCastException("Error in retrieving data. Please try again");
}
}
}
The Custom Interface namely SendMessage
is initialised in the onAttach
method above. This interface would be implemented in the MainActivity.java that we’ll be seeing shortly. The code for FragmentTwo.java class is given below.
package com.journaldev.passingdatabetweenfragments;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class FragmentTwo extends Fragment {
TextView txtData;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(
R.layout.fragment_two, container, false);
return rootView;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
txtData = (TextView)view.findViewById(R.id.txtData);
}
protected void displayReceivedData(String message)
{
txtData.setText("Data received: "+message);
}
}
The displayReceivedData()
would be called on the instance of FragmentTwo.java from inside the Custom Interface’s method inside the MainActivity.java as shown below.
package com.journaldev.passingdatabetweenfragments;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
public class MainActivity extends AppCompatActivity implements FragmentOne.SendMessage{
TabLayout tabLayout;
ViewPager viewPager;
ViewPagerAdapter viewPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(viewPagerAdapter);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
@Override
public void sendData(String message) {
String tag = "android:switcher:" + R.id.viewPager + ":" + 1;
FragmentTwo f = (FragmentTwo) getSupportFragmentManager().findFragmentByTag(tag);
f.displayReceivedData(message);
}
}
The sendData()
method in the above code gets triggered as soon as the Button in FragmentOne is pressed. We fetch the FragmentTwo that was already initialised in ViewPagerAdapter using the method findFragmentByTag. The output of the above application in action is given below. This brings an end to this tutorial. You can download the final Android PassingDataBetweenFragments Project from the link below.
Download Android Passing Data Between Fragments Example Project
Reference: Fragment Communication
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
hi I want to pass data between fragments using a custom broadcast receiver. how can I do that, please tell me.
- Zubair Hussain
I am using ViewPager2 and getting this error: Attempt to invoke virtual method ‘void com.pomtech.panda.Fragments.AdminAddNewDetailsFormFragment.displayReceiveMessage(java.lang.String, java.lang.String)’ on a null object reference
- Ramin Sultanzada
If you want to access the content value of a component in another Fragment, for instance a TextView, you can access it by finding the View for that Fragment via the container. In the onCreateView method of the Fragment where youwant to access the value, add the two lines at the bottom of my example code. Of course you need to figure out what index the View you are looking for has got in the collection of Views in the container. The View of the first Fragment has got index 0. Two lines of code, that’s all @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) { View view2 = container.getChildAt(0); TextView tvVehicleId = view2.findViewById(R.id.tvVehicleId);
- Henrik Stigebrandt
String tag = “android:switcher:”+R.id.viewPager+“:”+1; Log.e(“”,“Tags is “+tag); FragmentTwo f = (FragmentTwo) getSupportFragmentManager().findFragmentByTag(“android:switcher:”+R.id.viewPager+”:”+1); f.displayReceivedData(message); viewPager.setCurrentItem(1);
- AKSHAY SHEGAONKAR
you are awesome guy,i find solution for 2 days but you give me this solution in some minutes thanks a lot
- “jay”
It can be done by ViewModel…
- Rushikesh Patil
hy.this downlond lik is not valid.
- Thadi
Hello, this is the error in my codes java.lang.NullPointerException: Attempt to invoke virtual method ‘void com.example.admin.test2.MainScreen.displayReceivedData(java.lang.String)’ on a null… why would the f be null?
- Joric
Hi I did the codes in this website but I have an error which is “Cannot cast ‘com.example.admin.test2.Expense’ to ‘com.example.admin.test2.MainScreen’” I do not know what this means… I do net have view pager as my fragment transition, I have bottomnav as my fragment transition and I dont know what to do.
- Joric
Thank you very much! Thank you very much! Thank you very! I cannot express myself how glad I am because your post! I was searching for a solution for more than a week. Previously I was declaring ReceiverFragment receiverFragment = new ReceiverFragment(); in MainActivity. In the function to send the message to fragmentReceiver I was implementing like this: receiverFragment.getMessageFromSender(message); That way I was always getting the NullPointerException for the recyclerView in the ReceiverFragment.java. With your solution the recyclerView is found and everything is working as expected! Thank you very much, once more! link for the Stack Overflow: https://stackoverflow.com/questions/54464482/android-fragment-to-fragment-communication-update-recyclerview-of-the-receiver
- Aliton