59

My application has a Fragment inside its Activity. I would like to programmatically replace the fragment by another one from the current fragment itself.

For example, if I click on a button inside the fragment, the fragment should be replaced with another one, but the activity should remain the same.

Is it possible? If so, how to do it?

Léo Lam
  • 3,870
  • 4
  • 34
  • 44
bvitaliyg
  • 3,155
  • 4
  • 30
  • 46
  • this is exactly how framents work, look at fragment manager documentation: replace a fragment – sherpya Nov 04 '12 at 07:38
  • Thank you everyone, I created interface, that replace fragment and implement it in Activity. All works, FragmentManager works in Activity. – bvitaliyg Nov 04 '12 at 20:24
  • 1
    Does this answer your question? [Replacing a fragment from inside a fragment](https://stackoverflow.com/questions/53466141/replacing-a-fragment-from-inside-a-fragment) – Samir Alakbarov Jun 04 '20 at 20:17

8 Answers8

58

It's actually easy to call the activity to replace the fragment.

You need to cast getActivity():

((MyActivity) getActivity())

Then you can call methods from MyActivity, for example:

((MyActivity) getActivity()).replaceFragments(Object... params);

Of course, this assumes you have a replaceFragments() method in your activity that handles the fragment replace process.

Edit: @ismailarilik added the possible code of replaceFragments in this code with the first comment below which was written by @silva96:

The code of replaceFragments could be:

public void replaceFragments(Class fragmentClass) {
    Fragment fragment = null;
    try {
        fragment = (Fragment) fragmentClass.newInstance();
    } catch (Exception e) {
        e.printStackTrace();
    }
    // Insert the fragment by replacing any existing fragment
    FragmentManager fragmentManager = getSupportFragmentManager();
    fragmentManager.beginTransaction().replace(R.id.flContent, fragment)
            .commit();
}
ismailarilik
  • 2,236
  • 2
  • 26
  • 37
alorma
  • 924
  • 8
  • 10
  • 3
    The code of replaceFragments could be: `public void replaceFragments(Class fragmentClass) {` `Fragment fragment = null;` `try {` `fragment = (Fragment) fragmentClass.newInstance();` `} catch (Exception e) {` `e.printStackTrace();` `}` `// Insert the fragment by replacing any existing fragment` `FragmentManager fragmentManager = getSupportFragmentManager();` `fragmentManager.beginTransaction().replace(R.id.flContent, fragment).commit();` `}` – silva96 Aug 03 '15 at 14:51
  • 2
    @silva96 Can this comment get added to the original answer so it's easier to read please? :) Thanks. – admrply Dec 10 '15 at 01:35
  • 1
    @admrply I have to add that this is not a good practice, you should use callbacks to communicate between Activities and Fragments, as others say in the comments. I use a library called EventBus that is awesome for this. https://github.com/greenrobot/EventBus – silva96 Dec 10 '15 at 12:19
  • @silva96 Why is this not a good pratice? I have red [this](https://developer.android.com/guide/components/fragments.html#EventCallbacks) and it looks similar as the answer but i am new to android. What are the advantages of using callbacks instead? – Elkin Jan 29 '17 at 13:36
57

from the official docs:

// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();

In this example, newFragment replaces whatever fragment (if any) is currently in the layout container identified by the R.id.fragment_container ID. By calling addToBackStack(), the replaced fragment is saved to the back stack so the user can reverse the transaction and bring back the previous fragment by pressing the Back button.

The behavior you have described is exactly what fragments are designed to do. Please go through the official guide for a thorough understanding of fragments which will clear up all your questions.

http://developer.android.com/guide/components/fragments.html

Anup Cowkur
  • 20,443
  • 6
  • 51
  • 84
  • 3
    Where should this code go? In the activity that contains the fragments or in the fragment? – SleepNot Oct 21 '13 at 03:49
  • 1
    In the activity. Fragments should be separated, they should just notify the activity and then the activity should do the job. – Peter May 14 '14 at 13:54
31

Please note that fragment should NOT directly replace itself or any other fragments. Fragments should be separate entities. What fragment should do is to notify its parent activity that some event has happened. But it is, again, NOT a fragment job to decide what to do with that! It should be activity to decide to i.e. replace the fragment on phone, but to i.e. add another to existing one on tablets. So you are basically doing something wrong by design.

And, as others already mentioned, your activity should use FragmentManager ("native" or from compatibility library) to do the job (like replace() or add() or remove()):

http://developer.android.com/guide/components/fragments.html

Marcin Orlowski
  • 72,056
  • 11
  • 123
  • 141
  • Yep! I tried creating a fragment that had its own method .show() that would get the fragment manager and create itself, but it does not work. – Deminetix Sep 18 '13 at 05:17
  • The linked page does not back up your statement. The example given shows one fragment replacing itself, it only suggests defining a callback interface if one is required. – Leon Nov 06 '15 at 12:13
  • Read my answer again. – Marcin Orlowski Nov 06 '15 at 14:31
  • Somebody should tell the product managers, and designers that. in My case the parent activity is so far away that it has no idea what displayed in its view hierarchy. – Brill Pappin Jun 16 '17 at 11:40
4

Just as Marcin said, you shouldn't have a fragment start another fragment or activity. A better way to handle this situation is by creating a callback implementation for the main activity to handle requests such as start a new fragment. Here is a great example in the android developer guide.

DroidT
  • 3,168
  • 3
  • 31
  • 29
0

There is a way which works; Just (in the fragment) do the following:

getFragmentManager().beginTransaction()
.add(R.id. container_of_this_frag, new MyNewFragment())
.remove(this)
.commit();
laim2003
  • 299
  • 4
  • 19
0

When using nested fragments, we don't want every inner fragment replacement goes to the outer most activity. A mechanism allowing a fragment to notify its parent that it wants to change to another fragment can be useful.

Here is my code in Kotlin, I think it is easy to translate into java.

interface FragmentNavigator {
    fun navigateTo(fragment: Fragment)
}

class NavigableFragment: Fragment() {
    var navigator: FragmentNavigator? = null
    override fun onDetach() {
        super.onDetach()
        navigator = null
    }
}

Inner fragments need to extend NavigableFragment, and use following code to change itself to another fragment.

navigator?.navigateTo(anotherFragment)

Outer activities or fragments need to implement FragmentNavigator, and override navigateTo.

override fun navigateTo(fragment: Fragment) {
    supportFragmentManager.beginTransaction().replace(view_id, fragment).commit()
}

//Use childFragmentManager instead of supportFragmentManager a fragment

Finally in outer activities or fragments, override onAttachFragment

override fun onAttachFragment(fragment: Fragment?) {
    super.onAttachFragment(fragment)
    if(fragment is NavigableFragment) {
        fragment.navigator = this
    }
}
Jeffrey Chen
  • 1,777
  • 1
  • 18
  • 29
0

This worked for me:

getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
                    new MenuFragment()).commit();
0

For Kotlin.

           (activity as YourActivityLauncherFragment)
                .supportFragmentManager.beginTransaction()
                .replace(R.id.yourFragmentContainer, YourFragmentName()).setReorderingAllowed(true)
                .commit()
Stanislav
  • 191
  • 1
  • 5