23

I'm using a ViewPager together with a FragmentPagerAdapter to host three different fragments

[Fragment1][Fragment2][Fragment3]

What I'm trying to achieve is to successfully replace Fragment1 with a whole new fragment, Fragment4, if a specific task succeeds.

When I use..

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.fragment1_layout_id, fragment4);
transaction.commit();

..the fragment is replaced beautifully and Fragment4 is shown instead of Fragment1. Though as soon as I swipe all the way to Fragment3 and then back to Fragment4, Fragment1 has made a comeback.

Then again, if I use..

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.remove(fragment1);
transaction.commit();

..Fragment1 is removed and when I come back Fragment4 is there. So the problem with this solution is that I couldn't find a way to immediately show Fragment4 as Fragment1 is removed, even if I tried:

transaction.add(fragment4);
transaction.show(fragment4);

And here's how my FragmentPagerAdapter implementation looks like at the moment, without any transaction managing:

public static class PagerAdapter extends FragmentPagerAdapter {

    public PagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return VIEW_COUNT;
    }

    @Override
    public Fragment getItem(int position) {

        Fragment fragment = null;

        switch (position) {
        case 0:
            fragment = Fragment1.newInstance(context_);
            break;

        case 1:
            fragment = Fragment2.newInstance(context_);
            break;

        case 2:
            fragment = Fragment3.newInstance(context_);
            break;

        default:
            break;
        }

        return fragment;
    }
}

Edit.

So it seems like I wasn't totally clear with my question. I decided to remove all the spaghetti I managed to create earlier and tried to state that I had left them off (see bolded text above).

Anyway here's pretty much what I have been trying to do inside getItem():

@Override
public Fragment getItem(int position) {

    Fragment fragment = null;

    switch (position) {
    case 0:

        if (!app.isUserLoggedIn) {
            if (loginFragment_ == null) {
                loginFragment_ = LoginFragment.newInstance(context_);
                transaction_ = fragmentManager_.beginTransaction();

                if (logoutFragment_ != null) {
                    transaction_.remove(logoutFragment_);
                    logoutFragment_ = null;
                }

                transaction_.add(loginFragment_, "login");
                transaction_.commit();
            }

            if (fragmentManager_.findFragmentByTag("login") == null)
                fragment = LoginFragment.newInstance(context_);
            else
                fragment = fragmentManager_.findFragmentByTag("login");

        } else {
            if (logoutFragment_ == null) {                      
                logoutFragment_ = LogoutFragment.newInstance(context_);
                transaction_ = fragmentManager_.beginTransaction();

                if (loginFragment_ != null) {
                    transaction_.remove(loginFragment_);
                    loginFragment_ = null;
                }

                transaction_.add(logoutFragment_, "logout");
                transaction_.commit();
            }

            if (fragmentManager_.findFragmentByTag("logout") == null)
                fragment = LogoutFragment.newInstance(context_);
            else
                fragment = fragmentManager_.findFragmentByTag("logout");
        }
        break;

    case 1:
        fragment = HomeFragment.newInstance(context_);
        break;

    case 2:
        fragment = RegisterFragment.newInstance(context_);
        break;

    default:
        break;
    }

    return fragment;
}

With this code I get nothing done, but if someone sees what I'm doing wrong and would like to point me in the correct direction, I'd appreciate it a lot!

velu
  • 263
  • 1
  • 2
  • 6
  • I think you should change getItem in PagerAdapter. There is returned fragment which has to be visible. – pawelzieba Sep 16 '11 at 13:49
  • @dziobas That's exactly where I've been trying to do the magic I described in my question, with no luck. – velu Sep 16 '11 at 14:21
  • fragment2 is called when i click on tab1 , i dont know why tab2 is called? is adapter error? – Faisal Ashraf May 19 '15 at 11:28
  • Please see my [answer](https://stackoverflow.com/a/13997730/564626) to a similar question about how to insert/replace tabs with a `ViewPager` and `FragmentPagerAdapter`. – jfritz42 Dec 21 '12 at 22:06

5 Answers5

11

Try using FragmentStatePagerAdapter

http://android-developers.blogspot.com/2011_08_01_archive.html

coz it will remove the fragment as you swipe through the view(also when you call getitem), so you don't need to explicitly remove them yourself.

I've been having the same problem it works for me.

I try your code and remove the if (fragment!=null) block and it works.

axel22
  • 31,198
  • 9
  • 120
  • 134
Ridwan Yusuf
  • 254
  • 1
  • 8
  • 14
  • Can u show some code plz. I would be very grateful, because I followed your steps and I didn't get that I wanted... – cesards Oct 10 '12 at 14:35
3

Like Maurycy said, you need to call mAdapter.notifyDataSetChanged() whenever you want to tell the ViewPager that the fragments have been replaced. However, you also need to override the getItemPosition() abstract function in your adapter and return POSITION_NONE when called with an old, to be hidden, fragment as argument. Otherwise, ViewPager will retain all current fragments.

For more information and example code, see this answer to a related question.

Community
  • 1
  • 1
wize
  • 1,897
  • 1
  • 11
  • 12
0

Try setting offScreenPageLimit to 5 (or based on your usecase) to avoid reloading of the fragment so that what you had replaced will stay instead of getting reloaded when you swipe.

    mViewPager.setOffscreenPageLimit(5);
Shangeeth Sivan
  • 1,105
  • 14
  • 18
0

Shouldn't your getItem statement be returning fragment4 for case 0 in some circumstances?

Sashi Kolli
  • 741
  • 5
  • 6
  • Yes, it should and I've been trying to find out the correct way to do that all day long. I updated my question and added how I've been trying to do it so far. – velu Sep 16 '11 at 15:35
0

Hey I have solved this problem by using a List inside my FragmentPagerAdapter to handle the various fragments and then my getItem is like so....

    public void addScreen(String tag, Class<?> clss, Bundle args){
        if(clss!=null){
            TabInfo info = new TabInfo(tag, clss, args);
            screens.add(info);
        }
    }
@Override
    public Fragment getItem(int position) {
        TabInfo info = screens.get(position);
        return Fragment.instantiate(context, info.clss.getName(), info.args);
    }

I then programmatically remove/add/rearrange the list items (fragments) then call on the handler

mAdapter.notifyDataSetChanged()
Maurycy
  • 4,089
  • 7
  • 30
  • 41