Android Fragment - move from one View to another?

2019-01-24 07:49发布

问题:

Can i first add a Fragment to a View, then "detach" it, and then "re-attach" it to another View?

In code, i want to:

fragOne one = new fragOne();
getSupportFragmentManager().beginTransaction()
        .add(R.id.left, one, "tag").commit();

getSupportFragmentManager().beginTransaction()
        .detach(one).commit();      // or .remove(), or .addToBackStack(null).remove()

getSupportFragmentManager().executePendingTransactions();

getSupportFragmentManager().beginTransaction()
        .add(R.id.right, one).commit();

But it throws error:

04-05 13:28:03.492: E/AndroidRuntime(7195): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.trybackstack/com.example.trybackstack.MainActivity}: java.lang.IllegalStateException: Can't change container ID of fragment fragOne{40523130 #0 id=0x7f080000 tag}: was 2131230720 now 2131230721

Thanks for help!

回答1:

I had the same problem but I found that what I really needed was to reparent the fragment's view and not the fragment itself, thus avoiding any fragmentManager transaction.

View vv = fragment.getView();
ViewGroup parent = (ViewGroup)vv.getParent();
parent.removeView(vv);
newparent.addView(vv, layoutParams);


回答2:

after trying all the answers from similar questions, looks like i've found a way to do the trick.

First issue - you really have to commit and execute remove transaction before trying to add fragment to another container. Thanks for that goes to nave's answer

But this doesn't work every time. The second issue is a back stack. It somehow blocks the transaction.

So the complete code, that works for me looks like:

manager.popBackStackImmediate(null, manager.POP_BACK_STACK_INCLUSIVE);
manager.beginTransaction().remove(detailFragment).commit();
manager.executePendingTransactions();
manager.beginTransaction()
    .replace(R.id.content, masterFragment, masterTag)
    .add(R.id.detail, detailFragment, activeTag)
    .commit();              


回答3:

I guess you would have this figured out by now, but i dont't see any satisfactory answer. So, I'm posting this for others who may refer to this in the future.

If you want to move a fragment from one view to another you do the following:

android.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.remove(fragment1);
fragmentTransaction.commit();
fragmentManager.executePendingTransactions();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.containerToMoveTo, fragment1);
fragmentTransaction.commit();

This way you do not have to duplicate the fragment.



回答4:

Please check the solution,you need to create the new instance of the same fragment and instantiate it with state of the old fragment if you want to save the state of the old fragment.

 FragmentTransaction ft = mFragmentManager.beginTransaction();
    ft.remove(one);
    Fragment newInstance = fetchOldState(one);
    ft.add(R.id.right, newInstance);
    ft.commit();


//TO fetch the old state
    private Fragment fetchOldState(Fragment f)
        {
            try {
                Fragment.SavedState oldState= mFragmentManager.saveFragmentInstanceState(f);

                Fragment newInstance = f.getClass().newInstance();
                newInstance.setInitialSavedState(oldState);

                return newInstance;
            }
            catch (Exception e) // InstantiationException, IllegalAccessException
            {

            }
        }


回答5:

I have run into that problem as well. Sometimes moving fragments works, sometimes you have to create a new instance. It seems that moving fragments does not work, if the fragment keeps being in the "isRemoving" state. Being removed also seems to be prevented by having a fragment in the backstack.



回答6:

Adding to the Yan. Yurkin's answer. Make sure not to have any transitions applied to the transaction as these seem to delay the fragment from being detached.