En fait, il n'y a pas de dernier fragment ajouté à la pile car vous pouvez en ajouter plusieurs ou fragments à la pile en une seule transaction ou simplement supprimer des fragments sans en ajouter un nouveau.
Si vous voulez vraiment avoir une pile de fragments et pouvoir accéder à un fragment par son index dans la pile, vous feriez mieux d'avoir une couche d'abstraction sur le FragmentManager
et sa backstack. Voici comment vous pouvez le faire:
public class FragmentStackManager {
private final FragmentManager fragmentManager;
private final int containerId;
private final List<Fragment> fragments = new ArrayList<>();
public FragmentStackManager(final FragmentManager fragmentManager,
final int containerId) {
this.fragmentManager = fragmentManager;
this.containerId = containerId;
}
public Parcelable saveState() {
final Bundle state = new Bundle(fragments.size());
for (int i = 0, count = fragments.size(); i < count; ++i) {
fragmentManager.putFragment(state, Integer.toString(i), fragments.get(i));
}
return state;
}
public void restoreState(final Parcelable state) {
if (state instanceof Bundle) {
final Bundle bundle = (Bundle) state;
int index = 0;
while (true) {
final Fragment fragment =
fragmentManager.getFragment(bundle, Integer.toString(index));
if (fragment == null) {
break;
}
fragments.add(fragment);
index += 1;
}
}
}
public void replace(final Fragment fragment) {
fragmentManager.popBackStackImmediate(
null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
fragmentManager.beginTransaction()
.replace(containerId, fragment)
.addToBackStack(null)
.commit();
fragmentManager.executePendingTransactions();
fragments.clear();
fragments.add(fragment);
}
public void push(final Fragment fragment) {
fragmentManager
.beginTransaction()
.replace(containerId, fragment)
.addToBackStack(null)
.commit();
fragmentManager.executePendingTransactions();
fragments.add(fragment);
}
public boolean pop() {
if (isEmpty()) {
return false;
}
fragmentManager.popBackStackImmediate();
fragments.remove(fragments.size() - 1);
return true;
}
public boolean isEmpty() {
return fragments.isEmpty();
}
public int size() {
return fragments.size();
}
public Fragment getFragment(final int index) {
return fragments.get(index);
}
}
Maintenant , au lieu d'ajouter et de supprimer des fragments en appelant FragmentManager
directement, vous devez utiliser push()
, replace()
et les pop()
méthodes de FragmentStackManager
. Et vous pourrez accéder au fragment le plus haut en appelant simplement stack.get(stack.size() - 1)
.
Mais si vous aimez les hacks, j'ai d'autres moyens de faire des choses similaires. La seule chose que je dois mentionner est que ces hacks ne fonctionneront qu'avec des fragments de support.
Le premier hack consiste simplement à ajouter tous les fragments actifs au gestionnaire de fragments. Si vous remplacez simplement les fragments un par un et sortez le de la pile, cette méthode renverra le fragment le plus haut:
public class BackStackHelper {
public static List<Fragment> getTopFragments(
final FragmentManager fragmentManager) {
final List<Fragment> fragments = fragmentManager.getFragments();
final List<Fragment> topFragments = new ArrayList<>();
for (final Fragment fragment : fragments) {
if (fragment != null && fragment.isResumed()) {
topFragments.add(fragment);
}
}
return topFragments;
}
}
La deuxième approche est un événement plus hacky et vous permet d'obtenir tous les fragments ajoutés dans la dernière transaction pour laquelle addToBackStack
a été appelée:
package android.support.v4.app;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class BackStackHelper {
public static List<Fragment> getTopFragments(
final FragmentManager fragmentManager) {
if (fragmentManager.getBackStackEntryCount() == 0) {
return Collections.emptyList();
}
final List<Fragment> fragments = new ArrayList<>();
final int count = fragmentManager.getBackStackEntryCount();
final BackStackRecord record =
(BackStackRecord) fragmentManager.getBackStackEntryAt(count - 1);
BackStackRecord.Op op = record.mHead;
while (op != null) {
switch (op.cmd) {
case BackStackRecord.OP_ADD:
case BackStackRecord.OP_REPLACE:
case BackStackRecord.OP_SHOW:
case BackStackRecord.OP_ATTACH:
fragments.add(op.fragment);
}
op = op.next;
}
return fragments;
}
}
Veuillez noter que dans ce cas, vous devez mettre cette classe dans le android.support.v4.app
package.
FragmentTransaction.add(int containerViewId, Fragment fragment, String tag)
orFragmentTransaction.replace(int containerViewId, Fragment fragment, String tag)
doc