7

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.

2
  • You can try to create an instance variable of the Fragment with the setName() method in your Activity class. Assign the variable to the Fragment when you instantiate it. you can then call fragment.setName() from your activity Commented Jul 16, 2013 at 20:05
  • I have this problem, but calling fragment.setName() via a stored reference to it, isn't the problem. The problem is that from the fragment, the getActivity() returns null so that views cannot be accessed. I can access the views from the activity, though, and the fragment COULD put info into the views belonging to the fragment at configuration. But later, the getActivity() returns null and could it be something with the viewPager taking control of context so that getActivity is actually not valid? So one would need to request the view from the Viewpager? I am asking. Commented Mar 6, 2014 at 22:21

4 Answers 4

12

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.

Sign up to request clarification or add additional context in comments.

2 Comments

This should be the accepted answer. Thanks a lot. You are a life-saver.
You Save my hours. Thanks. Working perfect solution
7

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> 

3 Comments

This does not work when you rotate. Because when you rotate the activity and fragments are recreated which also recreates your SectionsPagerAdapter but it never calls getItem (Android recreates the fragments without calling getItem) meaning passOnToB remains null.
I edited my code so it will work after screen rotation. The trick is to set the callback not only in getItem(), but also include a custom method in the pager adapter that will search trough the fragments and set the callback manually, when the correct fragment is found. Now you only have to check if the callback is set and set it if not in the passOn method. I hope this is somewhat clear.
3

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.

6 Comments

Yes, I know this already. But what if I am trying to instantiate it using something like Frag1 fragment = (Frag1) mAppSectionsAdapter.getItem(0);? How I am supposed to use the method then without the null pointer exception?
It's like fragment.getView() is always null!
You want to get the reference from your adapter? I'm not at my computer but I can post code later if that's the issue.
Any help with mine please... stackoverflow.com/questions/39907625/…
Your answer always works for me in view pager thankyou man , only for you i starred the question now.. Thanx man :)
|
2

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(); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.