J'apprends à utiliser des fragments. J'ai trois instances de Fragment
qui sont initialisées en haut de la classe. J'ajoute le fragment à une activité comme celle-ci:
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 fonctionnent correctement. Chaque fragment est attaché à l'activité et est enregistré sans problème dans la pile arrière.
Donc, quand je lance A
, C
et puis B
, la pile ressemble à ceci:
| |
|B|
|C|
|A|
___
Et lorsque j'appuie sur le bouton «retour», il B
est détruit et C
reprend.
Mais, lorsque je lance fragment A
une deuxième fois, au lieu de reprendre à partir de la pile arrière, il est ajouté en haut de la pile arrière
| |
|A|
|C|
|A|
___
Mais je veux reprendre A
et détruire tous les fragments dessus (le cas échéant). En fait, j'aime juste le comportement par défaut de la pile arrière.
Comment faire cela?
Attendu: ( A
devrait être repris et les fragments supérieurs devraient être détruits)
| |
| |
| |
|A|
___
Edit: (suggéré par A - C)
Voici mon code d'essai:
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 est que, lorsque je lance A
, puis que je B
appuie sur «retour», il B
est supprimé et A
repris. et en appuyant une deuxième fois sur «retour», vous devez quitter l'application. Mais il montre une fenêtre vide et je dois appuyer une troisième fois pour la fermer.
Aussi, quand je lance A
, alors B
, puis C
, B
encore ...
Attendu:
| |
| |
|B|
|A|
___
Réel:
| |
|B|
|B|
|A|
___
Dois-je remplacer onBackPressed()
par une personnalisation ou est-ce que je manque quelque chose?
OnBackstackChangedListener
afin que vous puissiez garantir que vous avez affaire au bon fragment.OnBackstackChangedListener
.instanceof
:)A-B-C-B
et appuyez une fois en arrière, vous reviendrezA
et non pasC
. En effet,popBackStackImmediate
non seulement la balise donnée apparaît mais également tout ce qui précède. Y a-t-il du travail là-bas?Je pense que cette méthode résout votre problème:
qui a été initialement publié dans cette question
la source
Étape 1: Implémentez une interface avec votre classe d'activité
Étape 2: Lorsque vous appelez un autre fragment, ajoutez cette méthode:
la source
la source
la source
Une solution plus simple changera cette ligne
ft.replace(R.id.content_frame, A);
àft.add(R.id.content_frame, A);
Et dans votre mise en page XML, veuillez utiliser
Clickable
signifie qu'il peut être cliqué par un dispositif de pointeur ou être touché par un dispositif tactile.Focusable
signifie qu'il peut obtenir la mise au point à partir d'un périphérique d'entrée comme un clavier. Les périphériques d'entrée tels que les claviers ne peuvent pas décider à quelle vue envoyer ses événements d'entrée en fonction des entrées elles-mêmes, ils les envoient donc à la vue qui a le focus.la source