The scenario I am faced with, is in my application I have a single pane and dual pane style layout. Rather than individually handle every single navigation operation possible between the screens, for every different style of layout, I am using a function which sets up the layout correctly when given the desired screen.
It is basically a switch
statement for each screen in the app, with a nested switch
statement in each screen to handle each layout style. This is what I'm talking about in code:
protected void setupScreen() {
switch(currentScreen) {
case SCREEN_ONE:
switch(currentLayout) {
case SINGLE_PANE:
// Perform actions to setup the screen
break;
case DUAL_PANE:
// Perform actions to setup the screen
break;
}
break;
case SCREEN_TWO:
switch(currentLayout) {
case SINGLE_PANE:
// Perform actions to setup the screen
break;
case DUAL_PANE:
// Perform actions to setup the screen
break;
}
break
// ... etc ....
}
}
In the section where I want to perform the actions to setup the screen, this consists of the following basic three operations:
// Create the fragments if necessary
if (screenFragment == null) {
screenFragment = new myFragment();
}
// Remove the existing fragments from the layout views
// HOW???
// Add the fragments for this screen to the view
getSupportFragmentManager().beginTransaction().add(pane1.getId(), myFragment, "myFragment").commit();
As you can see, what I am struggling with is how to do the second step. How do you remove all Fragment
s from a given View
without knowing exactly which ones you are wanting to remove? The closest I have found is FragmentTransaction.replace()
which does successfully do this for every case but when it turns out you are replacing a Fragment
with the same fragment. In this case, it does not remove all, then add (like the documentation suggests), it just seems to remove. Is this an issue with using the compatibility libraries or is it not the way FragmentTransaction.replace()
should be used?
In any case, how should I go about doing this? Do I have to code a removeAllFragments()
function to go through every fragment and detach it or is there a way to do the first half of what the 'two in one' FragmentTransaction.replace()
function claims to do?
None of the other answers were really working for me. Here's what I did:
or, if you're forced to use it (but not recommended):
Also, if you're removing all fragments from the view multiple times, you might consider checking if the current frag is null or
isDetached()
orisRemoving()
or you might getNullPointerExceptions
.Update: The documentation for
getSupportFragmentManger().getFragments()
is apparently hidden now, but still works just fine in my code. Here's the screenshot of the documentation:Having said that, since it is hidden, they no longer want this method used, so see my update below.
Update 8-4-15: If you're not using the support library for fragments, there is unfortunately no
getFragments()
available, but there are still a couple, more inconvenient, options.fragment
atag
orid
upon creation, and iterate through them to process eachfragment
as desired.onAttachListener
so each time a newfragment
is attached to theactivity
, you can store thatfragment
, and then iterate through that data structure to process eachfragment
as desired.When not using the
getSupportFragmentManager()
, to process a transaction you will need to usegetFragmentManager()
instead.The typical mechanism is to use
FragmentManager.findFragmentByTag()
. You use this and add tags to your fragments (or the alternative for id's). This way you can determine what fragments are currently being managed. Then, once you have a handle to a present fragment (findFragmentByTag returns non-null), you can useFragmentManager.beginTransaction()
to start a FrgamentTransaction and remove / add the necessary fragments. Working in this way will allow you to avoid the 're-adding' process for the fragment you want to keep.What I'd probably do is have code like so: (warning psuedo code)
You should also consider sub-classes of your class instead of having 'everything in one class'. You have a fairly obvious case of Martin Fowler's Replace Conditional with Subclass. Otherwise, I fear this is going to be incredibly hard to manager when you add another screen.
If you use android.support.v4.app.Fragment you can do this:
Turns out
FragmentTransaction.replace()
is the correct operation and should work correctly. It only does not work when usingActionBarSherlock
andSherlockFragmentActivity
so I can only assume it is a bug in this compatibility library.I have confirmed this through using the code below to implement the desired behaviour through Android on API11+, the android compatibility library, and ActionBarSherlock. It only breaks in the last instance.
This is more or less how I have handled this. Have all your fragments implement an interface something like:
Make an enum corresponding to your fragments:
Then in your fragment switching activity:
You'll have to change things around a little to fit your particulars.