android – How to replace the activity's fragment from the fragment itself?-ThrowExceptions

Exception or error:

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?

How to solve:

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();
}

###

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

###

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

###

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.

###

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();

###

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
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *