web-dev-qa-db-fra.com

récupère le dernier fragment en pile

Comment puis-je obtenir la dernière instance de fragment ajoutée dans backstack (si je ne connais pas la balise fragment & id)?

FragmentManager fragManager = activity.getSupportFragmentManager();
FragmentTransaction fragTransacion = fragMgr.beginTransaction();

/****After add , replace fragments 
  (some of the fragments are add to backstack , some are not)***/

//HERE, How can I get the latest added fragment from backstack ??
89
Leem.fin

Vous pouvez utiliser la méthode getName() de FragmentManager.BackStackEntry qui a été introduite dans l'API de niveau 14. Cette méthode renverra une balise qui était celle que vous avez utilisée lorsque vous avez ajouté le fragment à la pile de disques avec addTobackStack(tag).

int index = getActivity().getFragmentManager().getBackStackEntryCount() - 1
FragmentManager.BackStackEntry backEntry = getFragmentManager().getBackStackEntryAt(index);
String tag = backEntry.getName();
Fragment fragment = getFragmentManager().findFragmentByTag(tag);

Vous devez vous assurer que vous avez ajouté le fragment à la pile comme ceci:

fragmentTransaction.addToBackStack(tag);
144
Deepak Goel
FragmentManager.findFragmentById(fragmentsContainerId) 

function retourne le lien vers le haut Fragment dans backstack. Exemple d'utilisation:

    fragmentManager.addOnBackStackChangedListener(new OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            Fragment fr = fragmentManager.findFragmentById(R.id.fragmentsContainer);
            if(fr!=null){
                Log.e("fragment=", fr.getClass().getSimpleName());
            }
        }
    });
46
ashakirov

J'ai personnellement essayé plusieurs de ces solutions et je me suis retrouvé avec cette solution de travail:

Ajoutez cette méthode utilitaire qui sera utilisée plusieurs fois ci-dessous pour obtenir le nombre de fragments dans votre pile de pile:

protected int getFragmentCount() {
    return getSupportFragmentManager().getBackStackEntryCount();
}

Ensuite, lorsque vous ajoutez/remplacez votre fragment à l'aide de la méthode FragmentTransaction, générez une balise unique pour votre fragment (par exemple, en utilisant le nombre de fragments dans votre pile):

getSupportFragmentManager().beginTransaction().add(yourContainerId, yourFragment, Integer.toString(getFragmentCount()));

Enfin, vous pouvez trouver n’importe lequel de vos fragments dans votre pile de pile avec cette méthode:

private Fragment getFragmentAt(int index) {
    return getFragmentCount() > 0 ? getSupportFragmentManager().findFragmentByTag(Integer.toString(index)) : null;
}

Par conséquent, il est facile de récupérer le fragment supérieur dans votre pile de pile en appelant:

protected Fragment getCurrentFragment() {
    return getFragmentAt(getFragmentCount() - 1);
}

J'espère que cela t'aides!

37
ptitvinou

Il y a une liste de fragments dans fragmentMananger. Sachez que la suppression d'un fragment ne diminue pas la taille de la liste (l'entrée du fragment devient null) Par conséquent, une solution valable serait:

public Fragment getTopFragment() {
 List<Fragment> fragentList = fragmentManager.getFragments();
 Fragment top = null;
  for (int i = fragentList.size() -1; i>=0 ; i--) {
   top = (Fragment) fragentList.get(i);
     if (top != null) {
       return top;
     }
   }
 return top;
}
6
Erez

La réponse donnée par deepak goel ne fonctionne pas pour moi car je suis toujours nul avec entry.getName();

Ce que je fais est de définir une balise sur le fragment de cette façon:

ft.add(R.id.fragment_container, fragmentIn, FRAGMENT_TAG);

Où ft est ma transaction de fragment et FRAGMENT_TAG est la balise. Ensuite, j'utilise ce code pour obtenir le fragment:

Fragment prev_fragment = fragmentManager.findFragmentByTag(FRAGMENT_TAG);
4
Eduardo

cette méthode d'assistance récupère un fragment du haut de la pile:

public Fragment getTopFragment() {
    if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
        return null;
    }
    String fragmentTag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
    return getSupportFragmentManager().findFragmentByTag(fragmentTag);
}
3
roghayeh hosseini

Kotlin

activity.supportFragmentManager.fragments.last()
3

vous pouvez utiliser getBackStackEntryAt () . Pour savoir le nombre d'entrées de l'activité dans le backstack, vous pouvez utiliser getBackStackEntryCount ()

int lastFragmentCount = getBackStackEntryCount() - 1;
3
Blackbelt

On dirait que quelque chose a changé pour le mieux, car le code ci-dessous fonctionne parfaitement pour moi, mais je ne l'ai pas trouvé dans les réponses déjà fournies.

Kotlin:

supportFragmentManager.fragments[supportFragmentManager.fragments.size - 1]

Java:

getSupportFragmentManager().getFragments()
.get(getSupportFragmentManager().getFragments().size() - 1)
2
Vasily Kravchenko

Je viens de prendre la réponse de @roghayeh hosseini (correcte) et je l’ai faite à Kotlin pour ceux d’ici 2017 :)

fun getTopFragment(): Fragment? {
    supportFragmentManager.run {
        return when (backStackEntryCount) {
            0 -> null
            else -> findFragmentByTag(getBackStackEntryAt(backStackEntryCount - 1).name)
        }
    }
}

* Ceci devrait être appelé de l'intérieur d'une activité.

Prendre plaisir :)

2
Shirane85

Gardez votre propre pile de retour: myBackStack. En tant que Add un fragment de FragmentManager, ajoutez-le également à myBackStack. Dans onBackStackChanged()sélectionnez myBackStack lorsque sa longueur est supérieure à getBackStackEntryCount.

2
Arne Evertsson

En réalité, aucun dernier fragment n'a été ajouté à la pile, car vous pouvez en ajouter plusieurs ou plusieurs dans 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 la FragmentManager et son 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);
  }
}

Au lieu d'ajouter et de supprimer des fragments en appelant directement FragmentManager, vous devez utiliser les méthodes Push(), replace() et pop() 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 la même chose. La seule chose que je dois mentionner, c'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 ne remplacez que les fragments un par un et que vous le retirez 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 event more hacky et vous permet d’obtenir tous les fragments ajoutés dans la dernière transaction pour laquelle addToBackStack a été appelé:

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 package Android.support.v4.app.

1
Michael

La réponse la plus élevée (Deepak Goel) n'a pas bien fonctionné pour moi. D'une manière ou d'une autre, la balise n'a pas été ajoutée correctement.

J'ai fini par envoyer l'ID du fragment via le flux (à l'aide d'intents) et de le récupérer directement à partir du gestionnaire de fragments.

0
htafoya

Si vous utilisez addToBackStack(), vous pouvez utiliser le code suivant.

List<Fragment> fragments = fragmentManager.getFragments(); activeFragment = fragments.get(fragments.size() - 1);

0
Akbar Kazimov

Ou vous pouvez simplement ajouter une balise lors de l'ajout de fragments correspondant à leur contenu et utiliser un simple champ String statique (vous pouvez également l'enregistrer dans un ensemble d'instances d'activité dans la méthode onSaveInstanceState (Bundle)) pour conserver la dernière balise de fragment ajoutée et obtenir ce fragment parTag () à tout moment vous avez besoin ...