move Android fragment to a different container Can't change container ID of fragment

12,395

Solution 1

I don't know if this is quite what you want but I made a little sample regarding your problem. Basically you'll be doing the right shifting using the layout file, having a wrapper container for each of those shifting fragments. The code sample is a little to big for an answer so I've posted it into a gist that you can find here. In that sample press each of the ListFragment's items(Fragment 1 -> Fragment 2 -> fragment 3) to see the behavior.

Solution 2

Yes container of the fragment can be changed using remove() function.

The problem here is commit(). It is an asynchronous call, and will schedule it to be on main thread. So to force the FragmentManager to do this immediately before adding it to the other container.

For this we will have to use executePendingTransactions() function. After calling this try adding the fragment to new container.

Docs : executePendingTransactions()

Code Sample :

FragmentManager fManager = getSupportFragmentManager();
FragGroups fragGroups = (FragGroups) fManager.findFragmentByTag("groups");
if (fragGroups != null) {
     fManager.beginTransaction().remove(fragGroups).commit();
     fManager.executePendingTransactions();
} else {
     fragGroups = new FragGroups();
}
if (mTwoPane) {
    fManager.beginTransaction().replace(R.id.fragment_container_groups, fragGroups, "groups").commit();
} else {
    fManager.beginTransaction().replace(R.id.fragment_container, fragGroups, "groups").commit();
}

Enjoy. Feed-backs are welcomed

Edit

I would like a add a point here. As I had same problem, came across to this thread and applied suggested changes. Problem still persisted. Then i looked into last comment down this thread that solved my problem: remove addToBackStack() method while committing a transaction or if you intentionally using it, remove the fragment from back stack before adding it to another container. Hope it will help to future reader.

Share:
12,395
Matthieu
Author by

Matthieu

There are 10 types of people in the world: those who understand binary, and those who don't. (credits)

Updated on July 27, 2022

Comments

  • Matthieu
    Matthieu almost 2 years

    Here is what I would like my application to do on a tablet. Fragment (0) has some menu that would display fragments (1)...(n) like this:

    -----------------
    |   |   |   |   |
    |   |   |   |   |
    |(0)| X | X | X |
    |   |   |   |   |
    |   |   |   |   |
    -----------------
     becomes
    -----------------
    |   |   |   |   |
    |   |   |   |   |
    |(0)|(1)| X | X |
    |   |   |   |   |
    |   |   |   |   |
    -----------------
     and then
    -----------------
    |   |   |   |   |
    |   |   |   |   |
    |(0)|(2)|(1)| X |
    |   |   |   |   |
    |   |   |   |   |
    -----------------
     etc... 
    

    Fragment0 never moves, the other ones are shifted to the right. Fragments going off the edge to the right will be destroyed.

    So I setup my XML layout with a horizontal LinearLayout and containing 4 FrameLayout with the proper IDs (fragment0... fragment3)

    I can instantiate and display fragment0 and then fragment1, but I am not able to shift it to the right after, I get:

    ERROR/AndroidRuntime(343): FATAL EXCEPTION: main
    java.lang.IllegalStateException: Can't change container ID of fragment ...
    

    The only related questions I have found are this one and that one, tried all the different solutions offered with no luck.

    Tried FragmentTransaction.remove() followed by .add(), tried .replace(), tried them in different orders and to commit half-way through (even trying to commit twice as somebody suggested), tried to call addToBackStack() ... still no luck.

    Question is whether it is possible to move the fragments like this with a FragmentTransaction. If yes, what am I doing wrong (and bonus, is it possible to animate that?). If no, what would be the proper way to implement this?

    Note that I don't want to re-instantiate the fragments every time (each do some queries on the web that can take some time). It's possible to extract all the data back to the activity to recreate one, but I'd rather not do that if possible...

  • Matthieu
    Matthieu over 11 years
    It does not do what I am looking for, but I am trying to change your code to do it... I'll post it if I am able to...
  • Matthieu
    Matthieu over 11 years
    Was able to do what I needed... Could not figure out how to push my changes to the gist you created, so I put it there: gist.github.com/4166640
  • midnite
    midnite about 11 years
    Excuse me. Is that a typo, that it should be LinearLayout instead of RelativeLayout in frag_fragaccordion.xml?
  • user
    user about 11 years
    @midnite Why do you ask that? Both samples use RelativeLayout in that layout file.
  • midnite
    midnite about 11 years
    i meant in @Matthieu example, the line 33 LinearLayout main_linear = (LinearLayout) getActivity().findViewById(R.id.main_linear); is strange to me.
  • user
    user about 11 years
    @midnite Well you should ask him, that is not in my code and I can't help you with that(that id also doesn't appear in that layout file?!?).
  • midnite
    midnite about 11 years
    @Luksprog, sorry to make you misunderstood. i am not challenging him, nor you neither. i just wanna see if that is a typo. And it may help others who need this answer as well :-)
  • user
    user about 11 years
    @midnite I understand that but I don't know Matthieu's code(and I think he probably used a LinearLayout instead of the RelativeLayout from my code)
  • Matthieu
    Matthieu over 10 years
    Yes, I was using a LinearLayout, I don't see how that really matters though
  • user
    user over 10 years
    @Matthieu This is an old question so I'm not sure what was the problem, but I think midnite was referring to a difference between our sample codes(yours being more developed).
  • Tom R
    Tom R over 10 years
    Excellent answer! May not be exactly what the original question was looking for but I found it extremely useful.
  • dell116
    dell116 over 10 years
    Pavan.....I don't even know you....you don't even know me....but I have some serious love for you, my friend.
  • Pavan Jaju
    Pavan Jaju over 10 years
    @TomR I am glad u found it useful :)
  • cesards
    cesards almost 10 years
    Nice. I wanted to do the same :D
  • Casey Perkins
    Casey Perkins almost 10 years
    The problem with this solution is that it is not possible to add the first transaction to the back stack. Doing so causes the original error "Can't change container ID" to appear again.