Replace a Fragment in a ViewPager using FragmentPagerAdapter

Go To StackoverFlow.com

0

I am using a ViewPager with 4 pages, and I'm looking for an efficient way to replace/switch between fragments in each page.

This is the interaction pattern that I'm trying to create:

  1. User presses a button on a page that currently holds fragment A
  2. Fragment A is swapped out for some new fragment B
  3. The user does some work in fragment B, and then presses a button when he/she is done
  4. Fragment B is removed, and is replaced by fragment A (the original fragment)

I've found a way to do this, but it seems to have significant flaws. The solution involves removing the original fragment, and then overriding getItemPosition (essentially the method described in this related question):

//An array to keep track of the currently visible fragment in each page
private final Fragment[] activeFragments= new Fragment[4];

public void openFragmentB(ViewPager pager, int position) {

    startUpdate(pager);

    //Remove the original fragment
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.remove(activeFragments[position]);
    transaction.commit();

    //Create a new tile search fragment to replace the original fragment
    activeFragments[position] = FragmentB.newInstance();
    pageStates[position] = PageState.STATE_B;

    finishUpdate(pager);
    notifyDataSetChanged();
}

@Override
public int getItemPosition(Object object) {

    //If the main fragment is not active, return POSITION_NONE
    if(object instanceof FragmentA) {
        FragmentA a = (FragmentA) object;
        if(pageStates[a.getPosition()] != PageState.STATE_A) {
            return POSITION_NONE;
        }
    }

    //If the secondary fragment is not active, return POSITION_NONE
    if(object instanceof FragmentB) {
        FragmentB b = (FragmentB) object;
        if(pageStates[b.getPosition()] != PageState.STATE_B) {
            return POSITION_NONE;
        }
    }

    return POSITION_UNCHANGED;
}

This method works, but has undesirable side effects. Removing the fragment and setting it's position to POSITION_NONE causes the fragment to be destroyed. So when the user finishes using FragmentB, I would need to create a new instance of FragmentA instead of reusing the original fragment. The main fragments in the pager (FragmentA in this example) will contain relatively large database backed lists, so I want to avoid recreating them if possible.

Essentially I just want to keep references to my 4 main fragments and swap them in and out of pages without having to recreate them every time. Any ideas?

2012-04-04 06:04
by theisenp
Fragments are also Views, you could create a layout with the Fragments you need to swap, then just use setVisibility() to remove and add them - adneal 2012-04-04 06:29


1

A simple way to avoid recreating your Fragments is to keep them as member variables in your Activity. I do this anyway in conjunction with onRetainCustomNonConfigurationInstance() order to retain my fragments during configuration changes (mostly screen rotation). I keep my Fragments in a 'retainer' object since onRetainCustomNonConfigurationInstance only returns a single object.

In your case, instead of calling Fragment.newInstance() all the time, just check to see if the fragments contained in the retainer object is null before creating a new one. If it isn't null, just re-use the previous instance. This checking should happen in your ViewPager adapter's getItem(int) method.

In effect, doing this basically means you are handling whether or not Fragments are recycled when getItem is called, and overriding the getItemPosition(Object) method to always return POSITION_NONE when for relevant Segments.

2012-09-26 22:00
by ebernie


1

FragmentPagerAdapter provides an overrideable method called getItemId that will help you here.

If you assign a unique long value to each Fragment in your collection, and return that in this method, it will force the ViewPager to reload a page when it notices the id has changed.

Better late than never, I hope this helps somebody out there!

2013-10-22 22:35
by Aaron Sarazan
Ads