I'm building an application that shows different fragments in a ViewPager
. I add these fragments to the ViewPager
like this:
public void intialiseViewPager()
{
List<Fragment> fragments = new Vector<Fragment>();
numberOfTabs = application.currentReport.getODTabsList().size();
for (int i = 0; i < numberOfTabs; i++)
{
ODTab tempTab = application.currentReport.getODTabsList().get(i);
if (tempTab.getTabType().equals(ODGrid.XML_GRID_ELEMENT))
{
GridFragment gridFragment = GridFragment.newInstance(tempTab.getTabId());
fragments.add(gridFragment);
}
else if (tempTab.getTabType().equals(ODChart.XML_CHART_ELEMENT))
{
NewChartFragment chartFragment = NewChartFragment.newInstance(tempTab.getTabId());
fragments.add(chartFragment);
}
}
Log.d(TAG, "Current report fragments set to adapter: "+fragments.toString());
mPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), fragments);
mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setOffscreenPageLimit(0);
mViewPager.setOnPageChangeListener(this);
}
As you can see I pass to the fragment a String (tempTab.getTabId()
), in this line:
GridFragment gridFragment = GridFragment.newInstance(tempTab.getTabId());
In the fragment itself I do this to initialize it:
public static final GridFragment newInstance(String tabId)
{
GridFragment f = new GridFragment();
Bundle bdl = new Bundle(2);
bdl.putString(TAB_ID, tabId);
f.setArguments(bdl);
return f;
}
@Override
public void onCreate(Bundle savedInstanceState)
{
String tabId = getArguments().getString(TAB_ID);
if (application.currentReport != null)
{
this.odTab = application.currentReport.getODTabByTabId(tabId);
}
else
{
startActivity(new Intent(getActivity(), LoginScrActivity.class));
}
super.onCreate(savedInstanceState);
}
All this is performed in order to not override the default empty constructor of the fragment, as I understand that this is not recommended.
Now I need to get the instance of the odTab
object that I put into the currently visible fragment in this line:
this.odTab = application.currentReport.getODTabByTabId(tabId);
Could someone please explain to me how this could be done? How do I get the currently visible fragment instance so I can pull the odTab object out of it?
UPDATE:
With the suggestions I received here I have added an odTab
object instance to the application class that is called currentVisibleTab
and I'm setting the instance of the odTab like this:
@Override
public void setUserVisibleHint(boolean isVisibleToUser)
{
Log.d(TAG, "setUserVisibleHint invoked!");
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser)
{
if (odTab != null && getActivity() != null)
{
Log.d(TAG, "Currently visable tab: "+odTab.getTabTitle());
application.currentVisibleTab = odTab;
}
}
}
UPDATE2:
This is my ViewPagerAdapter
:
public class ViewPagerAdapter extends FragmentPagerAdapter
{
private List<Fragment> fragments;
/**
* @param fm
* @param fragments
*/
public ViewPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
/* (non-Javadoc)
* @see android.support.v4.app.FragmentPagerAdapter#getItem(int)
*/
@Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
/* (non-Javadoc)
* @see android.support.v4.view.PagerAdapter#getCount()
*/
@Override
public int getCount() {
return this.fragments.size();
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
public void removeAllFragments()
{
this.fragments.clear();
}
public void addFragmentsListToAdapter(List<Fragment> fragments)
{
this.fragments.addAll(fragments);
}
public List<Fragment> getFragments()
{
return fragments;
}
}
In it I have a List
of fragments that are shown by the ViewPager
. This list is initialized like this:
List<Fragment> fragments = new Vector<Fragment>();
What I don't understand is how I get a reference to the current fragment that triggered the interface method from this list.
And this is not a related question but maybe you know the answer: What is the difference between List
and Vector
?
I still check this option out.
You can get the current visible fragment using viewpager.getCurrentItem() method in the following way:
Fragment fr = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + mViewPager.getCurrentItem());
thanks,
Sulabh
The way I've found the currently visible fragment is using
setUserVisibleHint
and an interface back to theViewPager
. This method is in the fragment class. Override it and use an interface to call back to yourViewPager
. If the fragment is visible - i.e. it returns true - then just use a reference to your fragment (either from the list backing your adapter or one you stored as an instance variable) to get whatever you need out of the fragment itself. I've added the code below.Declare an interface related to whatever you want to do. In my case I was using this to disable the
ViewPager
default x-direction listener when a Google Map instance was visible so that the scrolling of the map did not trigger the change of fragment.In the fragment:
One thing that was not obvious until I tried this out was the addition of the isAttached variable. I also override the fragments onAttach method and set this to true once it is called. Otherwise what happens is your fragment will be visible to the user and try to call the interface to your
ViewPager
before the interface is initialized.In my
ViewPager
I just implement the OnMapFragmentVisibleListener and then add the required methodIn my case I used it to turn off the
ViewPager
swipe function. However, I could have easily called back to a public method in my mapFragment. I happen to have 3 fragments in myViewPager
that I keep a reference to.Update
To find the fragment that is currently displayed, you first need to find out which fragment is being displayed. You can do this a number of ways. The easiest is to pass some descriptor back to your
ViewPager
/FragmentActivity
with the interface you created before.The problem with your setup is that you're using a
Vector
which is really a synchronizedList
to store your fragment references. As a result, there is no key value by which you can locate your fragments later. Fragments have the ability to be identified by a tag that is created during the fragment transaction when they are added to the fragment activity. However, in aViewPager
setup, you do not add the fragments individually and so can't add tags during the transaction.My solution has been to back my
BasePagerAdapter
with aHashMap
in which I store each fragment identified by a unique key.Then I use this in the adapter:
Because your references are stored to key values, it's easy to find the fragment you're looking for because you can just search by key from the
HashMap
and return.If you cannot change the setup to get away from the
Vector
you need to either (1) keep track of which fragment you add in which order (assuming fragments are not added and removed dynamically) so that you can get it by index or (2) keep separate references to each fragment.Another thing that makes this easier is that my fragments are all sub-classed. E.g. each fragment that performs a different function has its own class. As there is only one instance of each class it is easy to find since I do not have any duplicates. If you're using all generic members of the
Fragment
class you just need to implement some system of tagging that makes one of the approaches above possible.