Reputation: 731
I have a Fragment with a method setName() that changes an EditText text, by means of the setText function.
What is the best way to call that method from the activity that hosts that fragment by means of a ViewPager?
In other words, how can I access a Fragment's methods (which change that fragment's layout, for example) from the Activity that hosts that fragment by means of a ViewPager?
I am asking this because I have tried several ways, but always with errors.
Upvotes: 7
Views: 17459
Reputation: 881
Best way to do this, just call
CallingFragmentName fragment = (CallingFragmentName) viewPager
.getAdapter()
.instantiateItem(viewPager, viewPager.getCurrentItem());
It will re-instantiate your calling Fragment, so that it will not throw null pointer exception.
Upvotes: 12
Reputation: 9643
Fragment
private static FragmentName instance;
public static synchronized FragmentName getInstance()
{
return instance;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
instance=this;
....
}
public void methodName()
{...}
Activity
FragmentName.getInstance().methodName();
Upvotes: 2
Reputation: 141
I know this is a little late, but I ran into the same problem and maybe it will help others if you already solved it.
The first problem I found with ViewPager is that it is almost impossible to get a reference to a fragment. The fragments are created dynamically in getItem() and therefore you can't set an ID and they are automatically re-taged by the swicher, so you can't find it by tag either. There are some ways out there to do it, but they are all workarounds. (Update data in ListFragment as part of ViewPager)
The way I solved it was using essentially a double Callback. Fragment A has an interface implemented by the Main Activity, the Main Activity has a interface implemented by Fragment B. On e.g. a button clink in Fragment A the callback function in Main Activity is called, which than in turn calls the callback in Fragment B. Look at the code below. I hope I posted everything and it will help. btw, I have only tried this with a ViewPager, but I assume it would work with any sort of Fragment communication.
Main Avtivity java:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
public class MainActivity extends FragmentActivity implements FragmentA.Caller {
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
PassCallToB passOnToB = null;
FragmentManager myManager = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
MyManager = fm;
}
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
if(position == 0) {
fragment = new FragmentA();
} else if (position == 1) {
fragment = new FragmentB();
passOnToB = (PassCallToB)fragment;
}
return fragment;
}
@Override
public int getCount() {
return 2;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Frag A";
case 1:
return "Frag B";
}
return null;
}
public void setCallback() {
List<Fragment> frags = myManager.getFragments();
for(Fragment fragment : frags) {
if(fragment instanceof FragmentB){
passOnToB = (PassCallToB)fragment;
}
}
}
}
public interface PassCallToB {
public void passItOn();
}
@Override
public void CallB() {
if(passOnToB instanceof Fragment)
passOnToB.passItOn();
else {
mSectionsPagerAdapter.setCallback();
passOnToB.passItOn();
}
}
}
Main Activity xml:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<android.support.v4.view.PagerTitleStrip
android:id="@+id/pager_title_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#33b5e5"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:textColor="#fff" />
</android.support.v4.view.ViewPager>
Fragment A java:
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
public class FragmentA extends Fragment {
Button btnCallB = null;
Caller listener = null;
public FragmentA() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle inState) {
View rootView = inflater.inflate(R.layout.fragment_a, container, false);
btnCallB = (Button)rootView.findViewById(R.id.btnCallB);
btnCallB.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
listener.CallB();
}
});
return rootView;
}
public interface Caller {
public void CallB();
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof FragmentActivity) {
listener = (Caller) activity;
} else {
throw new ClassCastException(activity.toString() + " must implemenet listener");
}
}
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
}
Fragment A xml:
<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" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="This is Fragment A" />
<Button
android:id="@+id/btnCallB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/textView1"
android:text="Call Fragment B" />
</RelativeLayout>
Fragment B Java:
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.Toast;
public class FragmentB extends Fragment implements MainActivity.PassCallToB {
public FragmentB() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle inState) {
View rootView = inflater.inflate(R.layout.fragment_b, container, false);
return rootView;
}
@Override
public void passItOn() {
Toast.makeText(getActivity(), "Hello from B", Toast.LENGTH_SHORT).show();
}
}
Fragment B xml:
<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" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="This is Fragment B" />
</RelativeLayout>
Upvotes: 7
Reputation: 7663
You can access public methods within the fragments held by your ViewPager
. You need to either (1) store a reference to the Fragment
when you create it and add it to the list that will back your pager adapter or (2) you need to get a reference to the fragment from the pager adapter itself. For example:
Fragment fragmentA = null; //instance variable
fragmenA = new Fragment(); //whereever you instantiate your fragment
If your method is
public void setName(String args){
//do something
}
all you would do is call that method from the reference to the fragment held by your ViewPager
fragmentA.setName(args);
You pass whatever arguments you need just like calling a regular method. Note this ONLY works if you are calling a method within a fragment from its containing ViewPager
or FragmentActivity
. If you want to do the reverse, fragment to activity, you need to use an inerface.
Upvotes: 3