I\'m trying to use Fragment with a ViewPager
using the FragmentPagerAdapter
.
What I\'m looking for to achieve is to replace a fragment, positioned
There is another solution that does not need modifying source code of ViewPager
and FragmentStatePagerAdapter
, and it works with the FragmentPagerAdapter
base class used by the author.
I'd like to start by answering the author's question about which ID he should use; it is ID of the container, i.e. ID of the view pager itself. However, as you probably noticed yourself, using that ID in your code causes nothing to happen. I will explain why:
First of all, to make ViewPager
repopulate the pages, you need to call notifyDataSetChanged()
that resides in the base class of your adapter.
Second, ViewPager
uses the getItemPosition()
abstract method to check which pages should be destroyed and which should be kept. The default implementation of this function always returns POSITION_UNCHANGED
, which causes ViewPager
to keep all current pages, and consequently not attaching your new page. Thus, to make fragment replacement work, getItemPosition()
needs to be overridden in your adapter and must return POSITION_NONE
when called with an old, to be hidden, fragment as argument.
This also means that your adapter always needs to be aware of which fragment that should be displayed in position 0, FirstPageFragment
or NextFragment
. One way of doing this is supplying a listener when creating FirstPageFragment
, which will be called when it is time to switch fragments. I think this is a good thing though, to let your fragment adapter handle all fragment switches and calls to ViewPager
and FragmentManager
.
Third, FragmentPagerAdapter
caches the used fragments by a name which is derived from the position, so if there was a fragment at position 0, it will not be replaced even though the class is new. There are two solutions, but the simplest is to use the remove()
function of FragmentTransaction
, which will remove its tag as well.
That was a lot of text, here is code that should work in your case:
public class MyAdapter extends FragmentPagerAdapter
{
static final int NUM_ITEMS = 2;
private final FragmentManager mFragmentManager;
private Fragment mFragmentAtPos0;
public MyAdapter(FragmentManager fm)
{
super(fm);
mFragmentManager = fm;
}
@Override
public Fragment getItem(int position)
{
if (position == 0)
{
if (mFragmentAtPos0 == null)
{
mFragmentAtPos0 = FirstPageFragment.newInstance(new FirstPageFragmentListener()
{
public void onSwitchToNextFragment()
{
mFragmentManager.beginTransaction().remove(mFragmentAtPos0).commit();
mFragmentAtPos0 = NextFragment.newInstance();
notifyDataSetChanged();
}
});
}
return mFragmentAtPos0;
}
else
return SecondPageFragment.newInstance();
}
@Override
public int getCount()
{
return NUM_ITEMS;
}
@Override
public int getItemPosition(Object object)
{
if (object instanceof FirstPageFragment && mFragmentAtPos0 instanceof NextFragment)
return POSITION_NONE;
return POSITION_UNCHANGED;
}
}
public interface FirstPageFragmentListener
{
void onSwitchToNextFragment();
}
Hope this helps anyone!