I haven\'t found a simple way to get all currently active (visible, currently in Resumed state) Fragments in an Activity. Is it possible without custom bookkeeping in my Act
Here is a recursive solution in Kotlin. Given the top-most fragments of an activity, returns all the descendant fragments.
fun recursiveGetFragments(parents: List<Fragment>): List<Fragment> {
val result = parents.toMutableList()
for(root in parents) {
if (root.isVisible) {
result.addAll(recursiveGetFragments(root.childFragmentManager.fragments))
}
}
return result
}
It is used as:
val fragmentList = recursiveGetFragments(supportFragmentManager.fragments)
I resolved with this:
public ArrayList<Fragment> getAllFragments() {
ArrayList<Fragment> lista = new ArrayList<Fragment>();
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
try {
fragment.getTag();
lista.add(fragment);
} catch (NullPointerException e) {
}
}
return lista;
}
Looks like the API currently misses a method like "getFragments".
However using the event "onAttachFragment" of class Activity it should be quite easy to do what you want. I would do something like:
List<WeakReference<Fragment>> fragList = new ArrayList<WeakReference<Fragment>>();
@Override
public void onAttachFragment (Fragment fragment) {
fragList.add(new WeakReference(fragment));
}
public List<Fragment> getActiveFragments() {
ArrayList<Fragment> ret = new ArrayList<Fragment>();
for(WeakReference<Fragment> ref : fragList) {
Fragment f = ref.get();
if(f != null) {
if(f.isVisible()) {
ret.add(f);
}
}
}
return ret;
}
In case there's no ready method to read the state from the object (isActive() in the example), I would override onResume and onPause to set a flag (could be just a bool field).
That's already some own bookkeeping, but still very limited in my opinion considering the quite specific goal you want to achieve (status dependent list).
If you use Android Support Library, then you can call hidden FragmentManager.getFragments()
method:
public List<Fragment> getVisibleFragments() {
List<Fragment> allFragments = getSupportFragmentManager().getFragments();
if (allFragments == null || allFragments.isEmpty()) {
return Collections.emptyList();
}
List<Fragment> visibleFragments = new ArrayList<Fragment>();
for (Fragment fragment : allFragments) {
if (fragment.isVisible()) {
visibleFragments.add(fragment);
}
}
return visibleFragments;
}
Another way to do this would be to put tags on your fragments when you add them to the activity.
For example, if you dynamically add 4 fragments, you can add them like:
for (int i = 0; i < NUM_FRAGMENTS; i++){
MyFragment fragment = new Fragment(i);
fragmentTransaction.add(R.id.containerId, fragment, SOME_CUSTOM_PREFIX + i).commit()
}
Then, if you need to get all the fragments back later, you can do:
for (int i = 0; i < NUM_FRAGMENTS; i++) {
String tag = SOME_CUSTOM_PREFIX + i;
fragmentList.add((MyFragment) fragmentManager.findFragmentByTag(tag));
}
android.support.v4.app.FragmentManager
has a method called getFragments()
which does exactly what you need, but it was never accessible. Suddenly, though, it is, but I'm not sure if that's intended because it's still marked as hidden.
/**
* Get a list of all fragments that have been added to the fragment manager.
*
* @return The list of all fragments or null if none.
* @hide
*/
public abstract List<Fragment> getFragments();
The regular android.app.FragmentManager
doesn't have this method at all, but if really needed, you can access the same object by getting the field mActive
via reflection (be careful there: starting with API 26, its type is a SparseArray
instead of List
). Use at own risk :)