I have 3 fragments in a ViewPager Activity. All 3 fragments have input fields. Here I am trying to pass first two fragments data to third fragment. I read few posts here and
Okay, I Had same issue to pass data(not just string) between two tabs in a ViewPager. So here is what i did. I Use interfaces to communicate between the different components.
The data passes this way:
Tab 1 -> Activity -> VewPageAdapter -> Tab 2
create an interface.
OnCartsDataListener mOncarOnCartsDataListener;
public interface OnCartsDataListener {
public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mOncarOnCartsDataListener = (OnCartsDataListener)activity;
}catch (ClassCastException e){
}
}
// now call mOncarOnCartsDataListener.onCartsDataReceived(data) when you have the data
Implement the interface and override the method
ViewPagerAdapter adapter;
adapter = new ViewPagerAdapter(getSupportFragmentManager(), Titles, Numboftabs);
@Override
public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels) {
Log.d(TAG, "data received to Activity... send to view pager");
adapter.onCartsDataReceived(cartsViewModels);
}
3.IN ViewPagerAdapter
Also implements the interface and override the method
@Override
public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels) {
Log.d(TAG, "data received to view pager... sending to tab 2");
if(tab2!=null){
tab2.onCartsDataReceived(cartsViewModels);
}else{
Log.d(TAG, "tab2 is null");
}
}
Also implements the interface and override the method
@Override
public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels) {
Log.d(TAG, "Finally ! received data to tab 2");
if(cartsViewModels!=null){
for(CartsViewModel cart : cartsViewModels){
Log.d(TAG,"got it :"+cart.getCartName());
}
}
}
Since AndroidX, you can create a ViewModel
and share data between Activity and all fragments within ViewPager
Read here how to
Can you do something like this? First create any data structure like Arraylist in your main activity. Then send a reference of that data model to your fragments. Now update that data when, on change your text fields. By doing this all the fragment can see updated values. So fragments can update this data itself and we don't need to send that data since it is already shared. I'll explain this using your example. Try to improve this. You can maintain fragment specific data model then each fragment can access data with the knowledge of that data owner.
TabsPagerAdapter.java
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm,SubmitPostActivity activity){
super(fm);
}
@Override
public Fragment getItem(int index) {
switch(index) {
case 0 : //PostInfoFragment
return new PostInfoFragment(0,activity);
case 1 : //LocationInfoFragment
return new LocationInfoFragment(1,activity);
case 2 : //PersonalInfoFragment
return new PersonalInfoFragment(2,activity);
}
return null;
}
@Override
public int getCount() {
return 3;
}
}
ViewPagerActivity -- >
package com.jbandroid;
public class SubmitPostActivity extends FragmentActivity implements ActionBar.TabListener,LocationInfoFragment.setLocationInfo{
private ViewPager viewpager;
private ActionBar actionBar;
private TabsPagerAdapter mAdapter;
FragmentManager manager;
PersonalInfoFragment frag;
List<String> location;
/*private MenuItem myActionMenuItem;
private Button myActionButton;*/
//Tab titles
private String[] tabs = {"Post Info" , "Location Info" , "Personal Info" };
public List<String> dataModel = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.action_submit_post);
viewpager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
manager = getSupportFragmentManager();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager(),this);
//viewpager.setOffscreenPageLimit(2);
viewpager.setAdapter(mAdapter);
//actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
for (String tab : tabs){
actionBar.addTab(actionBar.newTab().setText(tab).setTabListener(this));
}
if(savedInstanceState != null){
actionBar.setSelectedNavigationItem( savedInstanceState.getInt("tab",0));
}
}
}
1st Fragment =>
public class PostInfoFragment extends Fragment {
private MenuItem myActionMenuItem;
private Button myActionButton;
private ActionBar actionBar;
private String post_title, post_desc,post_status;
private EditText submit_post_title, submit_post_desc;
private int position;
private Resources res;
SubmitPostActivity callingActivity;
List<String> post_details;
public PostInfoFragment(int position,SubmitPostActivity callingActivity )
{
this.callingActivity = callingActivity;
this.position = position;
}
//RelativeLayout rel_submit_post_start_date,rel_submit_post_end_date;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_post_info,
container, false);
/*if(!imageLoader.isInited()){*/
initImageLoader();
/*}*/
//handler = new Handler();
submit_post_title = (EditText) rootView
.findViewById(R.id.submit_post_title);
submit_post_desc = (EditText) rootView
.findViewById(R.id.submit_post_description);
actionBar = getActivity().getActionBar();
setHasOptionsMenu(true);
post_details = new ArrayList<String>();
res = getResources();
setListeners();
Log.d("postinfo_oncreate view", "postinfo_oncreate view");
//this is editText onchange listner do the same for submit_post_desc as well
submit_post_title.addTextChangedListener( new TextWatcher()
{
@Override
public void onTextChanged( CharSequence s, int start, int before, int count )
{
}
@Override
public void beforeTextChanged( CharSequence s, int start, int count, int after )
{
}
@Override
public void afterTextChanged( Editable s )
{
if( callingActivity != null )
{
//use this.position in order to update relevant data
List<String> post_details = callingActivity.dataModel;
if( post_details == null )
{
post_details = new ArrayList<String>();
}
post_details.add(s.toString());
}
}
} );
return rootView;
}
//making sure if the parent activity has implemented interface
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
callingActivity = (SubmitPostActivity) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ "must implemet setPostInfo");
}
Log.d("postinfo_onattach", "postinfo_onattach");
}
}
Please not that this may not compile as it is. Try to get the concept.