Search code examples
androidtabsandroid-tabhost

android, dynamically change a fragment inside a tab


I'm trying to change the content of a tab that was created using FragmentTabHost and getSupportFragmentManager(), but I'm not sure how to do it. Here is what I have:

mTabHost = new FragmentTabHost(this);
    setContentView(mTabHost);

    mTabHost.setup(this, getSupportFragmentManager(),R.id.menu_settings);
    mTabHost.addTab(mTabHost.newTabSpec("A").setIndicator("A"),
            A.class, null);
    mTabHost.addTab(mTabHost.newTabSpec("B").setIndicator("B"),
            B.class, null);
    mTabHost.addTab(mTabHost.newTabSpec("C").setIndicator("C"),
            C.class, null);

Each class loaded extends fragment and on onCreateView they inflate their layout.

the issue is that I have a dialog inside one of them ( for example A.class ), and depending of the response of the dialog, I need to navigate to a fragment D, placing it on tab C How should I do this? I could communicate from the dialog to the activity that creates the tabs and specify the fragments, but I don't know how to change the fragment that is inside a tab ( in this case C ).

As a summary, I need to change fragment C to D inside a tab where C was placed. I'm using the support library.

Thanks!!


Solution

  • Create a class acts like an fragment container.

    for example:

    public class FragmentContainer extends SherlockFragment implements OnBackStackChangedListener {
    public static final String PARAM_CONTENT_FRAGMENT = "param_content_fragment";
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    
        return inflater.inflate(R.layout.frag_container, null);
    }
    
    public void replaceContent(Class<? extends Fragment> clz, Bundle args) {
        FragmentTransaction tx = getChildFragmentManager().beginTransaction();
    
        tx.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    
        // save
        Fragment curFrag = getChildFragmentManager().findFragmentById(R.id.fragment_content);
        tx.addToBackStack(curFrag.getClass().getSimpleName());
    
        // change
        try {
            Fragment newFragment = clz.newInstance();
            newFragment.setArguments(args);
            tx.replace(R.id.fragment_content, newFragment, clz.getClass().getSimpleName());
            tx.commit();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    
    }
    
    @Override
    public void onResume() {
        super.onResume();
        Fragment f = getChildFragmentManager().findFragmentById(R.id.fragment_content);
        if (f == null) {
            Class<? extends Fragment> claz = (Class<? extends Fragment>) getArguments().getSerializable(
                    PARAM_CONTENT_FRAGMENT);
            FragmentTransaction tx = getChildFragmentManager().beginTransaction();
            try {
                f = claz.newInstance();
                f.setTargetFragment(this, 0);
                tx.add(R.id.fragment_content, f);
                tx.commit();
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
    
        }
    }
    

    Several key point here:

    1. Init the third tab with FragmentContainer.class and provide C.class as an fragment arguments. (argument key is PARAM_CONTENT_FRAGMENT)

    2. onCreateView() Just create a FrameLayout with id @+id/fragment_content, this is where we place child fragment.

    3. onResume() Place child fragment into FrameLayout if not exists.

    4. replaceContent() Call this method When Fragment-C wants to change it-self to Fragment-D.

    In Frament-C, for example:

    ((FragmentContainer)getParentFragment() ).replaceContent( D.class, null );