Saturday 23 June 2012

Communication between Fragments in ViewPager

In Previous exercise "ViewPager" (and fix of "NullPointerException of ViewPager when change orientation"), I create a ViewPager with three independent Fragments. Now, I want to make some input (EditText) from Fragment A, then transfer it to Fragment B.

Communication between Fragments in ViewPager


With FragmentManager, we can access another fragment from our current fragment by calling findFragmentByTag(<tag of target fragment>). But, what's the tag of Fragment B? I can't found any method something like setTag()!

Luckly; I found getTag() method to get the tag name of current fragment. So I create a mechanism to access the tag across fragments via the main activity, AndroidViewPagerActivity. - Call getTag() in onCreateView() of MyFragmentB. Then pass it to the main activity AndroidViewPagerActivity. When MyFragmentA need to pass something to MyFragmentB, it retrieve it from AndroidViewPagerActivity.

Modify the main activity, AndroidViewPagerActivity.java, to have a String TabFragmentB; and implement setTabFragmentB() and getTabFragmentB() to access it.
package com.exercise.AndroidViewPager;

import java.util.ArrayList;

import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;

public class AndroidViewPagerActivity extends FragmentActivity {

ViewPager mViewPager;
TabsAdapter mTabsAdapter;

String TabFragmentB;

public void setTabFragmentB(String t){
TabFragmentB = t;
}

public String getTabFragmentB(){
return TabFragmentB;
}

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

mViewPager = new ViewPager(this);
mViewPager.setId(R.id.pager);
setContentView(mViewPager);

final ActionBar bar = getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);

mTabsAdapter = new TabsAdapter(this, mViewPager);
mTabsAdapter.addTab(bar.newTab().setText("Fragment A"),
MyFragmentA.class, null);
mTabsAdapter.addTab(bar.newTab().setText("Fragment B"),
MyFragmentB.class, null);
mTabsAdapter.addTab(bar.newTab().setText("Fragment C"),
MyFragmentC.class, null);

if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
}

}

@Override
protected void onSaveInstanceState(Bundle outState) {
//super.onSaveInstanceState(outState);
outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
}

public static class TabsAdapter extends FragmentPagerAdapter
implements ActionBar.TabListener, ViewPager.OnPageChangeListener {

private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();

static final class TabInfo {
private final Class<?> clss;
private final Bundle args;

TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}

public TabsAdapter(FragmentActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}

public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}

@Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub

}

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// TODO Auto-generated method stub

}

@Override
public void onPageSelected(int position) {
// TODO Auto-generated method stub
mActionBar.setSelectedNavigationItem(position);
}

@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub

}

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Object tag = tab.getTag();
for (int i=0; i<mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
}

@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub

}

@Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}

@Override
public int getCount() {
return mTabs.size();
}

}

}


Modify MyFragmentA.java and /res/layout/fragment_a.xml to add a ExitText and a Butten to send something.

package com.exercise.AndroidViewPager;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MyFragmentA extends Fragment {

EditText A_input;
Button A_enter;

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

A_input = (EditText)myFragmentView.findViewById(R.id.a_input);
A_enter = (Button)myFragmentView.findViewById(R.id.a_enter);
A_enter.setOnClickListener(A_enterOnClickListener);

return myFragmentView;
}

OnClickListener A_enterOnClickListener
= new OnClickListener(){

@Override
public void onClick(View arg0) {

String textPassToB = A_input.getText().toString();

String TabOfFragmentB = ((AndroidViewPagerActivity)getActivity()).getTabFragmentB();

MyFragmentB fragmentB = (MyFragmentB)getActivity()
.getSupportFragmentManager()
.findFragmentByTag(TabOfFragmentB);

fragmentB.b_updateText(textPassToB);

Toast.makeText(getActivity(),
"text sent to Fragment B:\n " + TabOfFragmentB,
Toast.LENGTH_LONG).show();
}};

}


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="It's Fragment A" />
<EditText
android:id="@+id/a_input"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/a_enter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Enter to Fragment B"/>
</LinearLayout>


Modify MyFragmentB.java and /res/layout/fragment_b.xml to receive something.

package com.exercise.AndroidViewPager;

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;
import android.widget.Toast;

public class MyFragmentB extends Fragment {

TextView b_received;

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

b_received = (TextView)myFragmentView.findViewById(R.id.b_received);
String myTag = getTag();

((AndroidViewPagerActivity)getActivity()).setTabFragmentB(myTag);

Toast.makeText(getActivity(),
"MyFragmentB.onCreateView(): " + myTag,
Toast.LENGTH_LONG).show();

return myFragmentView;
}

public void b_updateText(String t){
b_received.setText(t);
}

}


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="It's Fragment B" />
<TextView
android:id="@+id/b_received"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="center"
android:src="@drawable/ic_launcher"/>
</LinearLayout>


Download the files.

Next:
- AsyncTask run in background thread of a invisible Fragment of ViewPager


No comments:

Post a Comment