Comment reprendre un Fragment de la BackStack si il existe
Je suis en train d'apprendre comment utiliser des fragments. J'ai trois instances de Fragment
qui sont initialisés à la tête de classe. Je suis l'ajout du fragment à une activité de ce genre:
De la déclaration et initialisation:
Fragment A = new AFragment();
Fragment B = new BFragment();
Fragment C = new CFragment();
Remplacement/Ajout:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, A);
ft.addToBackStack(null);
ft.commit();
Ces extraits sont travail correctement. Chaque fragment est attaché à l'activité, et est enregistré dans la pile de retour sans aucun problème.
Donc quand je lance A
, C
, puis B
, la pile ressemble à ceci:
| |
|B|
|C|
|A|
___
Et lorsque j'appuie sur le bouton "retour", B
est détruit et C
est repris.
Mais, lorsque je lance fragment A
un deuxième temps, plutôt que de reprendre à partir de l'arrière de la pile, il est ajouté en haut de la pile de retour
| |
|A|
|C|
|A|
___
Mais je veux reprendre A
et de détruire tous les fragments sur le dessus de celui-ci (le cas échéant). En fait, j'aime juste le défaut de retour de la pile de comportement.
Comment puis-je y arriver?
Attendus: (A
devrait être repris et haut fragments doivent être détruits)
| |
| |
| |
|A|
___
Edit: (suggéré par Un--C)
C'est que j'essaie de code:
private void selectItem(int position) {
Fragment problemSearch = null, problemStatistics = null;
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
String backStateName = null;
Fragment fragmentName = null;
boolean fragmentPopped = false;
switch (position) {
case 0:
fragmentName = profile;
break;
case 1:
fragmentName = submissionStatistics;
break;
case 2:
fragmentName = solvedProblemLevel;
break;
case 3:
fragmentName = latestSubmissions;
break;
case 4:
fragmentName = CPExercise;
break;
case 5:
Bundle bundle = new Bundle();
bundle.putInt("problem_no", problemNo);
problemSearch = new ProblemWebView();
problemSearch.setArguments(bundle);
fragmentName = problemSearch;
break;
case 6:
fragmentName = rankList;
break;
case 7:
fragmentName = liveSubmissions;
break;
case 8:
Bundle bundles = new Bundle();
bundles.putInt("problem_no", problemNo);
problemStatistics = new ProblemStatistics();
problemStatistics.setArguments(bundles);
fragmentName = problemStatistics;
default:
break;
}
backStateName = fragmentName.getClass().getName();
fragmentPopped = manager.popBackStackImmediate(backStateName, 0);
if (!fragmentPopped) {
ft.replace(R.id.content_frame, fragmentName);
}
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(backStateName);
ft.commit();
//I am using drawer layout
mDrawerList.setItemChecked(position, true);
setTitle(title[position]);
mDrawerLayout.closeDrawer(mDrawerList);
}
Le problème c'est que quand je lance A
et puis B
, puis appuyez sur la touche 'retour', B
est supprimé et A
est repris. et en appuyant sur "retour", un deuxième temps de sortir de l'application. Mais il montre une fenêtre vide et je dois appuyer sur retour pour une troisième fois pour la fermer.
Aussi, lorsque je lance A
, puis B
, puis C
, puis B
encore...
Prévu:
| |
| |
|B|
|A|
___
Réel:
| |
|B|
|B|
|A|
___
Dois-je remplacer onBackPressed()
avec toute personnalisation ou ai-je raté quelque chose?
Vous devez vous connecter pour publier un commentaire.
La lecture de la la documentation, il y a un moyen pour pop, la pile de retour fondée sur la transaction, le nom ou l'id fourni par commettre. En utilisant le nom peut être plus facile car elle ne nécessite pas de suivi d'un nombre qui peut changer et renforce le "uniques pile de retour d'entrée" de la logique.
Puisque vous voulez une seule pile de retour entrée par
Fragment
, faire le dos nom de l'état le Fragment du nom de la classe (viagetClass().getName()
). Puis lors d'un remplacement deFragment
, utilisez lepopBackStackImmediate()
méthode. Si elle retourne true, cela signifie qu'il existe une instance de ce Fragment dans la pile de retour. Si non, de l'exécution du Fragment de la logique de remplacement.MODIFIER
C'est parce que le
FragmentTransaction
est ajouté à la pile de retour pour nous assurer que nous pouvons pop les fragments sur le dessus plus tard. Une solution rapide pour ce qui est primordialonBackPressed()
et la finition de l'Activité si l'arrière de la pile ne contient que des 1Fragment
Au sujet de la double pile de retour, l'instruction conditionnelle qui remplace le fragment s'il n'a pas été sauté, il est clairement différents que ce que mon code original extrait de l'. Ce que vous faites est d'ajouter à la pile de retour, indépendamment de si oui ou non la pile de retour a été sauté.
Quelque chose comme cela devrait être plus proche de ce que vous voulez:
Le conditionnel était un peu changé depuis la sélection de la même fragment alors qu'il était visible également causé des entrées en double.
Mise en œuvre:
Je vous suggère fortement de ne pas prendre la mise à jour
replaceFragment()
méthode se distingue comme vous l'avez fait dans votre code. La logique est contenue dans cette méthode et des pièces en mouvement autour de peut causer des problèmes.Cela signifie que vous devez copier la mise à jour
replaceFragment()
méthode dans votre classe puis changerainsi, il est tout
EDIT #2
De mettre à jour le tiroir lorsque la pile de retour changements, une méthode qui accepte dans un Fragment et compare les noms de classe. Si tout correspond, modifier le titre et la sélection. Également ajouter un
OnBackStackChangedListener
et de l'avoir appeler votre méthode de mise à jour s'il y a un Fragment.Par exemple, dans l'Activité du
onCreate()
, ajouterEt l'autre méthode:
Maintenant, chaque fois que la pile de retour changements, le titre et vérifié la position de refléter le visible
Fragment
.setTitle(title[position]);
et changé l'élément sélectionné de la navigation tiroir parmDrawerList.setItemChecked(position, true);
. Ce n'est pas d'aujourd'hui quand je presse le bouton de retour et de reprise d'un fragment de labackstack
. Le titre et l'élément sélectionné dans la navigation de tiroir n'est pas mis à jour. Où je peux placer cette mise à jour de code pour faire la mise à jour?onResume
de chaque fragment. Mais il faudra faire plus de codes dans tous les frgament. Est-il un bon moyen?onResume()
.fragment
est unnested fragment
et il a trois enfants. Le problème est que le parent fragment de la vue est primordial lorsque je reprends à partir debackstack
. Comment puis-je éviter cela? Avez vous vu quelque chose comme ça avant?fragment
lors de la reprise de backstack?View
là. Faire une nouvelle question, expliquer le problème en détail, et ajouter tout code ainsi que les captures d'écran.OnBackstackChangedListener
de sorte que vous pouvez garantir que vous avez affaire avec le droit Fragment.OnBackstackChangedListener
ainsi.instanceof
au lieu de cela, sur le Fragment retourné parfindFragmentById
?instanceof
🙂A-B-C-B
et appuyez sur la touche de retour une fois que vous serez de retour àA
et pas de retour àC
. C'est parce que lapopBackStackImmediate
non seulement apparaît la balise donnée, mais aussi tout ce qui est ci-dessus. Il y a tout un travail autour de là?Je pense que cette méthode ma résoudre votre problème:
qui a été posté dans
Cette Question
Étape 1: Implémenter une interface avec votre classe d'activité
Étape 2: Lorsque vous appelez un autre fragment ajouter cette méthode:
Solution plus facile sera la modification de cette ligne
ft.replace(R.id.content_frame, A);
pour
ft.add(R.id.content_frame, A);
Et à l'intérieur de votre mise en page XML, veuillez utiliser
Clickable
signifie qu'il peut être cliqué par un périphérique de pointage ou d'être exploité par un périphérique tactile.Focusable
signifie qu'il peut gagner le focus à partir d'un périphérique d'entrée comme le clavier. Périphériques d'entrée tels que les claviers ne peut pas décider de vue qui envoyer son entrée à des événements à partir des données lui-même, de sorte qu'ils envoient à la vue qui a le focus.