0

I want to replace a Fragment by a new Fragment when an onClick method is called. I wanted to do it this way:

  FragmentTransaction transaction = getFragmentManager().beginTransaction();

  transaction.remove(this);
  transaction.addToBackStack(null);
  transaction.add(new ChooseCocktailFragment(), null);

  transaction.commit();

The only thing that happens is the current Fragment is removed and the new one doesn't show. What am I doing wrong here?

Also, I use a ViewPager and this is the first time for me working with fragments. Usually I would have a Container with its ID but here the ViewPager contains the fragments, therefore I don't know how to use the transaction.replace(...) method.

Chad Bingham
  • 28,578
  • 19
  • 82
  • 110
Tobias Kuess
  • 649
  • 2
  • 12
  • 27
  • why not use transaction.replace() instead? that way you don't need to do separate remove & add calls – panini Nov 19 '13 at 21:05
  • because i need to add an fragment container transaction.replace(R.id.fragment_container, newFragment); and I don't know what to insert here as a value. – Tobias Kuess Nov 19 '13 at 21:11
  • The code above only adds and removes fragments to and from the FragmentManager. It does nothing regarding displaying them within your UI. If you are using ViewPager you really need to use a PagerAdapter as Mansoulx says below. – Kuffs Nov 19 '13 at 21:26
  • **"...this is the first time for me working with fragments."** One thing to understand about Fragments is that normally one Fragment should not know about the existence of any other Fragment unless the second Fragment is a child of the first. Fragments and FragmentTransactions should be managed by the Activity. In your case, your onClick(...) method should call a callback method defined in an interface implemented by the Activity and the Activity should be responsible for control of replacing the Fragment with another. – Squonk Nov 19 '13 at 21:48

3 Answers3

1

You should use a FragmentPagerAdapter which is adequate to put Fragments inside ViewPagers.

A complete tutorial from android developer here

EDIT:

First of all, you need to override the getItemPosition of the adapter, and return the POSITION_NONE constant in order to be able to replace pager's fragments.

@Override
public int getItemPosition(Object object)
{
    return POSITION_NONE;
}

Then create a listner for handling fragment switching:

public interface MyListener
{
   public void onFragmentChange();
}

Your adapter should implements the listner and add some code inside onFragmentChange() method:

public class TabsPagerAdapter extends FragmentPagerAdapter {

    private FragmentManager fm;
    public TabsPagerAdapter(FragmentManager fm) {
        super(fm);
        this.fm = fm;
    }

    @Override
    public Fragment getItem(int index) {

        switch (index) {
        case 0:
            fragment1 = TopRatedFragment.newInstance(this); 
            return fragment1;
        case 1:
            // ...
            return fragment2;
        case 2:
            // ...
            return fragment3;
        case 3:
            // ...
            return fragment4;
        }

        return null;
    }

        @Override
        public int getCount() {
            // get item count - equal to number of tabs
            return 4;
        }
        public void onFragmentChange(){
            fm.beginTransaction().remove(fragment1).commit();
                        fragment1 = NewFragment.newInstance();
                        notifyDataSetChanged(); // notify the viewpager adapter that content has changed
        }


    }

Pass an instance of the listner in the fragment you want to remove/replace later :

public class TopRatedFragment extends Fragment {

    public static TopRatedFragment newInstance(MyListner listner) {
        this.myListner = listner;
        return new TopRatedFragment (); 
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_top_rated, container, false);

        return rootView;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // some logical here ... and when you want to change fragment do this
        myListner.onFragmentChange();
    }
}

Here is some more explanation of this.

You should also read about FragmentStatePagerAdapter : here

Hope it helps !

Community
  • 1
  • 1
S.Thiongane
  • 6,703
  • 3
  • 34
  • 51
  • I am trying to do this, but setCurrenItem always throws NullPointerException. The thing is that i want to replace a fragment if a button of this fragment is clicked.. – Tobias Kuess Nov 19 '13 at 22:23
  • you want to replace the current fragment when button is clicked ? do you want to create the new fragment after button click, or you just want to set all pages of ViewPager an go to another fragment on button click ? please answer – S.Thiongane Nov 19 '13 at 22:25
  • I want to replace on fragment on button click. You could say that the fragment should replace itself on a click. I have several Tabs. And if one Tab is choosen and a button is clicked there, the tab should display another fragment. I hope you can follow me. I looked for dozens of tutorials now but i couldn't find any which seems to fit my need. – Tobias Kuess Nov 19 '13 at 23:00
  • ok i misunderstood. Edit your question and post your layouts and java code ! – S.Thiongane Nov 19 '13 at 23:04
  • Thank you so far. I will do so as soon as I got home! I know what ViewPager does and what i need the FragmentPager Adapter for. Tabs and sidescrolling them itself does work. But the problem is I dont know how to replace these things. I hope you can help later on. – Tobias Kuess Nov 20 '13 at 07:29
  • code is here! It is almost the same like mine. If i get the solution here i can easily transfer it – Tobias Kuess Nov 20 '13 at 09:22
  • Oh sorry :/ I will do this afterwards for people with the same problem. It will make it easier for them. Can you see the problem I have after seeing the code? – Tobias Kuess Nov 20 '13 at 10:31
  • i have edited my answer and added some useful links. Good luck. – S.Thiongane Nov 20 '13 at 11:23
  • Thank you so much for your help ! – Tobias Kuess Nov 20 '13 at 11:53
0

You forget hide your fragment after another fragment is added up on your fragment.

Just add more a statement transaction.hide(Your_Fragment) before transaction.commit()

thanhnh
  • 231
  • 1
  • 2
  • 5
0

@mansoulx

Here is my code which my answer refers to. Since i implemented it using a tutorial it is very similiar, just Tab names and the content of the tabs changed. I also have 4 tabs, not three - but the problem would be the same:

TabsPagerAdapter.java

public class TabsPagerAdapter extends FragmentPagerAdapter {

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

@Override
public Fragment getItem(int index) {

    switch (index) {
    case 0:
        return new Fragment1();
    case 1:
        return new Fragment2();
    case 2:
        return new Fragment3();
    }

    return null;
}

@Override
public int getCount() {
    // get item count - equal to number of tabs
    return 3;
}

}

MainActivity.java

public class MainActivity extends FragmentActivity implements
    ActionBar.TabListener {

private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
// Tab titles
private String[] tabs = { "Tab1", "Tab2", "Tab3" };

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Initilization
    viewPager = (ViewPager) findViewById(R.id.pager);
    actionBar = getActionBar();
    mAdapter = new TabsPagerAdapter(getSupportFragmentManager());

    viewPager.setAdapter(mAdapter);
    actionBar.setHomeButtonEnabled(false);
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);        

    // Adding Tabs
    for (String tab_name : tabs) {
        actionBar.addTab(actionBar.newTab().setText(tab_name)
                .setTabListener(this));
    }

@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
    // on tab selected
    // show respected fragment view
    viewPager.setCurrentItem(tab.getPosition());
}

@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}

viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

@Override
public void onPageSelected(int position) {
    // on changing the page
    // make respected tab selected
    actionBar.setSelectedNavigationItem(position);
}

@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}

@Override
public void onPageScrollStateChanged(int arg0) {
}
});

let's say all Fragments would look like this:

Fragment1.java

public class TopRatedFragment extends Fragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.fragment_top_rated, container, false);

    return rootView;
}

}

The thing which should be done now is: Replace Fragment1 on Tab1 with FragmentNew which should appear in Tab1 too! The OnClick-Event takes place in the fragment1.java for example...

Tobias Kuess
  • 649
  • 2
  • 12
  • 27