Below is my code which has 3 Fragment classes
each embedded with each of the 3 tabs on ViewPager
. I have a menu option. As shown in the onOpt
by selecting an option, I need to update the fragment that is currently visible.
To get a reference to currently visible fragment, assume you have a reference to ViewPager
as mPager
. Then following steps will get a reference to currentFragment
:
PageAdapter adapter = mPager.getAdapter();
int fragmentIndex = mPager.getCurrentItem();
FragmentStatePagerAdapter fspa = (FragmentStatePagerAdapter)adapter;
Fragment currentFragment = fspa.getItem(fragmentIndex);
The only cast used line 3 is valid usually. FragmentStatePagerAdapter
is an useful adapter for a ViewPager.
When we use the viewPager, a good way to access the fragment instance in activity is instantiateItem(viewpager,index). //index- index of fragment of which you want instance.
for example I am accessing the fragment instance of 1 index-
Fragment fragment = (Fragment) viewPageradapter.instantiateItem(viewPager, 1);
if (fragment != null && fragment instanceof MyFragment) {
((MyFragment) fragment).callYourFunction();
}
This is more future-proof than the accepted answer:
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
/* ------------------------------------------------------------------------------------------ */
// region Private attributes :
private Context _context;
private FragmentManager _fragmentManager;
private Map<Integer, String> _fragmentsTags = new HashMap<>();
// endregion
/* ------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------ */
// region Constructor :
public MyFragmentPagerAdapter(Context context, FragmentManager fragmentManager) {
super(fragmentManager);
_context = context;
_fragmentManager = fragmentManager;
}
// endregion
/* ------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------ */
// region FragmentPagerAdapter methods :
@Override
public int getCount() { return 2; }
@Override
public Fragment getItem(int position) {
if(_fragmentsTags.containsKey(position)) {
return _fragmentManager.findFragmentByTag(_fragmentsTags.get(position));
}
else {
switch (position) {
case 0 : { return Fragment.instantiate(_context, Tab1Fragment.class.getName()); }
case 1 : { return Fragment.instantiate(_context, Tab2Fragment.class.getName()); }
}
}
return null;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// Instantiate the fragment and get its tag :
Fragment result = (Fragment) super.instantiateItem(container, position);
_fragmentsTags.put(position, result.getTag());
return result;
}
// endregion
/* ------------------------------------------------------------------------------------------ */
}
FragmentStatePagerAdapter
has a private instance variable called mCurrentPrimaryItem
of type Fragment
. One can only wonder why Android devs did not supplied it with a getter. This variable is instantiated in setPrimaryItem()
method. So, override this method in such a way for you to get the reference to this variable. I simply ended up with declaring my own mCurrentPrimaryItem
and copying the contents of setPrimaryItem()
to my override.
In your implementation of FragmentStatePagerAdapter
:
private Fragment mCurrentPrimaryItem = null;
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment)object;
if (fragment != mCurrentPrimaryItem) {
if (mCurrentPrimaryItem != null) {
mCurrentPrimaryItem.setMenuVisibility(false);
mCurrentPrimaryItem.setUserVisibleHint(false);
}
if (fragment != null) {
fragment.setMenuVisibility(true);
fragment.setUserVisibleHint(true);
}
mCurrentPrimaryItem = fragment;
}
}
public TasksListFragment getCurrentFragment() {
return (YourFragment) mCurrentPrimaryItem;
}
You can define the PagerAdapter
like this then you will able to get any Fragment
in ViewPager
.
private class PagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
public PagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment) {
mFragmentList.add(fragment);
}
}
To get the current Fragment
Fragment currentFragment = mPagerAdapter.getItem(mViewPager.getCurrentItem());
This is the simplest hack:
fun getCurrentFragment(): Fragment? {
return if (count == 0) null
else instantiateItem(view_pager, view_pager.currentItem) as? Fragment
}
(kotlin code)
Just call instantiateItem(viewPager, viewPager.getCurrentItem()
and cast it to Fragment
. Your item would already be instantiated. To be sure you can add a check for getCount
.
Works with both FragmentPagerAdapter
and FragmentStatePagerAdapter
!