Existe-t-il un moyen de mettre en œuvre onBackPressed()
dans Android Fragment similaire à celui que nous implémentons dans Android Activity?
Comme le cycle de vie du fragment n'a pas onBackPressed()
. Existe-t-il une autre méthode alternative pour contourner onBackPressed()
les fragments d'Android 3.0?
android
android-fragments
onbackpressed
Android_programmer_camera
la source
la source
Réponses:
J'ai résolu de cette manière la dérogation
onBackPressed
dans l'activité. TousFragmentTransaction
sontaddToBackStack
avant de valider:la source
À mon avis, la meilleure solution est:
SOLUTION JAVA
Créez une interface simple:
Et dans votre activité
Enfin dans votre fragment:
SOLUTION KOTLIN
1 - Créer une interface
2 - Préparez votre activité
3 - Implémentez dans votre fragment cible
la source
R.id.main_container
? Est-ce l'ID du FragmentPager?.?
) et appliquer des valeurs non nulles (!!
) peut conduire à des NPE - la distribution n'est pas toujours sûre. Je préfère écrireif ((fragment as? IOnBackPressed)?.onBackPressed()?.not() == true) { ... }
ou plus kotliney(fragment as? IOnBackPressed)?.onBackPressed()?.not()?.let { ... }
.onBackPressed()?.takeIf { !it }?.let{...}
?.not()
renvoie juste l'inverse.val fragment = this.supportFragmentManager.findFragmentById(R.id.flContainer) as? NavHostFragment val currentFragment = fragment?.childFragmentManager?.fragments?.get(0) as? IOnBackPressed currentFragment?.onBackPressed()?.takeIf { !it }?.let{ super.onBackPressed() }
Ceci est pour les personnes qui utilisent Kotlin et NavigationControllerSelon @HaMMeRed, la réponse est le pseudocode comment cela devrait-il fonctionner. Disons que votre activité principale est appelée et
BaseActivity
qu'elle contient des fragments enfants (comme dans l'exemple de la bibliothèque SlidingMenu). Voici les étapes:Nous devons d'abord créer une interface et une classe qui implémentent son interface pour avoir une méthode générique
Créer une interface de classe
OnBackPressedListener
Créer une classe qui met en œuvre les compétences de
OnBackPressedListener
Depuis, nous allons travailler sur notre code
BaseActivity
et ses fragmentsCréez un auditeur privé au-dessus de votre classe
BaseActivity
créer une méthode pour définir l'écouteur dans
BaseActivity
en remplacement
onBackPressed
mettre en œuvre quelque chose comme çadans votre fragment,
onCreateView
vous devez ajouter notre auditeurVoila, maintenant, lorsque vous cliquez en arrière sur un fragment, vous devez attraper votre méthode personnalisée sur le dos.
la source
onBackPressed()
quel fragment était affiché lorsque le bouton de retour a été enfoncé?((BaseActivity)activity).setOnBackPressedListener(new OnBackpressedListener(){ public void doBack() { //...your stuff here }});
Cela a fonctionné pour moi: https://stackoverflow.com/a/27145007/3934111
la source
Si vous vouliez ce type de fonctionnalité, vous devrez la remplacer dans votre activité, puis ajouter un
YourBackPressed
interface à tous vos fragments, que vous appelez le fragment approprié chaque fois que vous appuyez sur le bouton Précédent.Edit: je voudrais ajouter ma réponse précédente.
Si je devais le faire aujourd'hui, j'utiliserais une diffusion, ou éventuellement une diffusion ordonnée si je m'attendais à ce que d'autres panneaux soient mis à jour à l'unisson vers le panneau de contenu principal / principal.
LocalBroadcastManager
dans la bibliothèque de support peut vous aider, et vous envoyez simplement la diffusiononBackPressed
et vous abonnez dans vos fragments qui vous intéressent. Je pense que la messagerie est une implémentation plus découplée et évoluerait mieux, donc ce serait ma recommandation officielle de mise en œuvre maintenant. Utilisez simplement leIntent
action de comme filtre pour votre message. envoyez votre nouvellement crééACTION_BACK_PRESSED
, envoyez-le de votre activité et écoutez-le dans les fragments appropriés.la source
LocalBroadcastManager
vous ne pouvez pas faire d'émissions commandéesRien de tout cela n'est facile à mettre en œuvre et ne fonctionnera pas de manière optimale.
Les fragments ont un appel de méthode onDetach qui fera le travail.
CECI FERA LE TRAVAIL.
la source
isRemoving()
comme décrit dans stackoverflow.com/a/27103891/2914140 .Si vous utilisez
androidx.appcompat:appcompat:1.1.0
ou au-dessus, vous pouvez ajouter unOnBackPressedCallback
à votre fragment comme suitVoir https://developer.android.com/guide/navigation/navigation-custom-back
la source
androidx-core-ktx
, vous pouvez utiliserrequireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { /* code to be executed when back is pressed */ }
LifecycleOwner
paramètre doit être ajouté comme dans cet exemple. Sans cela, tous les fragments commencés par la suite seront appeléshandleBackPressed()
si le bouton de retour est enfoncé.Ajoutez simplement
addToBackStack
pendant la transition entre vos fragments comme ci-dessous:si vous écrivez
addToBackStack(null)
, il le traitera de lui-même mais si vous donnez une balise, vous devez la gérer manuellement.la source
puisque cette question et certaines des réponses ont plus de cinq ans, permettez-moi de partager ma solution. Ceci est un suivi et une modernisation de la réponse de @oyenigun
MISE À JOUR: À Au bas de cet article, j'ai ajouté une implémentation alternative utilisant une extension de fragment abstraite qui n'impliquera pas du tout l'activité, ce qui serait utile pour toute personne ayant une hiérarchie de fragments plus complexe impliquant des fragments imbriqués qui nécessitent un comportement arrière différent.
J'avais besoin de l'implémenter car certains des fragments que j'utilise ont des vues plus petites que je voudrais ignorer avec le bouton de retour, telles que les petites vues d'informations qui apparaissent, etc., mais cela est bon pour tous ceux qui ont besoin de remplacer le comportement de le bouton de retour à l'intérieur des fragments.
Tout d'abord, définissez une interface
Cette interface, que j'appelle
Backable
(je suis un adepte des conventions de dénomination), a une seule méthodeonBackPressed()
qui doit retourner uneboolean
valeur. Nous devons appliquer une valeur booléenne, car nous devrons savoir si la pression sur le bouton de retour a «absorbé» l'événement de retour. Renvoyertrue
signifie que c'est le cas, et qu'aucune action supplémentaire n'est nécessaire, sinon,false
indique que l'action de retour par défaut doit toujours avoir lieu. Cette interface doit être son propre fichier (de préférence dans un package distinct nomméinterfaces
). N'oubliez pas que la séparation de vos classes en packages est une bonne pratique.Deuxièmement, trouvez le fragment supérieur
J'ai créé une méthode qui renvoie le dernier
Fragment
objet de la pile arrière. J'utilise des balises ... si vous utilisez des identifiants, apportez les modifications nécessaires. J'ai cette méthode statique dans une classe utilitaire qui traite des états de navigation, etc ... mais bien sûr, mettez-la là où elle vous convient le mieux. Pour l'édification, j'ai mis le mien dans une classe appeléeNavUtils
.Assurez-vous que le nombre de piles de retour est supérieur à 0, sinon un
ArrayOutOfBoundsException
pourrait être lancé lors de l'exécution. S'il n'est pas supérieur à 0, retournez null. Nous vérifierons une valeur nulle plus tard ...Troisièmement, implémentez dans un fragment
Implémentez l'
Backable
interface dans le fragment dans lequel vous devez remplacer le comportement du bouton de retour. Ajoutez la méthode d'implémentation.Dans le
onBackPressed()
remplacement, mettez la logique dont vous avez besoin. Si vous souhaitez que le bouton Précédent ne fasse pas apparaître la pile arrière (comportement par défaut), retournez true , que votre événement de retour a été absorbé. Sinon, retournez false.Enfin, dans votre activité ...
Redéfinissez la
onBackPressed()
méthode et ajoutez-y cette logique:Nous obtenons le fragment actuel dans la pile arrière, puis nous effectuons une vérification nulle et déterminons s'il implémente notre
Backable
interface. Si c'est le cas, déterminez si l'événement a été absorbé. Si oui, nous en avons fini aveconBackPressed()
et pouvons revenir. Sinon, traitez-le comme une contre-pression normale et appelez la super méthode.Deuxième option pour ne pas impliquer l'activité
Parfois, vous ne voulez pas que l'activité gère cela du tout, et vous devez le gérer directement dans le fragment. Mais qui dit que tu ne peux pas avoir de fragments avec une API de contre-presse? Étendez simplement votre fragment à une nouvelle classe.
Créez une classe abstraite qui étend Fragment et implémente l'
View.OnKeyListner
interface ...Comme vous pouvez le voir, tout fragment qui se prolonge
BackableFragment
capturera automatiquement les clics en arrière en utilisant l'View.OnKeyListener
interface. Appelez simplement laonBackButtonPressed()
méthode abstraite à partir de laonKey()
méthode implémentée en utilisant la logique standard pour discerner une pression sur le bouton de retour. Si vous devez enregistrer des clics sur les touches autres que le bouton Précédent, assurez-vous simplement d'appeler lasuper
méthode lors de la substitutiononKey()
dans votre fragment, sinon vous remplacerez le comportement dans l'abstraction.Simple à utiliser, il suffit d'étendre et de mettre en œuvre:
Puisque la
onBackButtonPressed()
méthode dans la super classe est abstraite, une fois que vous étendez, vous devez implémenteronBackButtonPressed()
. Il revientvoid
car il a juste besoin d'effectuer une action au sein de la classe de fragments et n'a pas besoin de relayer l'absorption de la presse à l'activité. Assurez- vous d'appeler laonBackPressed()
méthode Activity si tout ce que vous faites avec le bouton de retour ne nécessite pas de manipulation, sinon le bouton de retour sera désactivé ... et vous ne le voulez pas!Avertissements Comme vous pouvez le voir, cela définit l'écouteur clé sur la vue racine du fragment, et nous devons le concentrer. S'il y a des textes d'édition impliqués (ou toute autre vue volant le focus) dans votre fragment qui étend cette classe, (ou d'autres fragments internes ou vues qui ont la même), vous devrez gérer cela séparément. Il y a un bon article sur l' extension d'un EditText pour perdre le focus sur une presse arrière.
J'espère que quelqu'un trouve cela utile. Codage heureux.
la source
super.onBackPressed();
deux fois?currentFragment
. Si le fragment n'est pas nul et que le fragment implémente l'Backable
interface, aucune action n'est effectuée. Si le fragment n'est pas nul et qu'il n'implémente PASBackable
, nous appelons la super méthode. Si le fragment est nul, il passe au dernier super appel.currentFragment
n'est pas nul et est une instance de Backable et qu'il est détaché (nous avons appuyéback
sur le bouton et fermé le fragment), la première occurrence desuper.onBackPressed();
est appelée, puis la seconde.La solution est simple:
1) Si vous avez une classe de fragments de base que tous les fragments étendent, ajoutez ce code à sa classe, sinon créez une telle classe de fragments de base
2) Dans votre classe Activity, remplacez onBackPressed comme suit:
3) Dans votre classe Fragment, ajoutez le code souhaité:
la source
onBackPressed()
amener le Fragment à se détacher de l'Activité.Selon @Sterling Diaz, je pense qu'il a raison. MAIS une situation sera fausse. (ex. Rotation de l'écran)
Donc, je pense que nous pourrions détecter si
isRemoving()
faut atteindre les objectifs.Vous pouvez l'écrire sur
onDetach()
ouonDestroyView()
. C'est du travail.la source
Eh bien, je l'ai fait comme ça, et ça marche pour moi
Interface simple
FragmentOnBackClickInterface.java
Exemple d'implémentation
MyFragment.java
puis juste remplacer onBackPressed dans l'activité
la source
Vous devez ajouter une interface à votre projet comme ci-dessous;
Et puis, vous devez implémenter cette interface sur votre fragment;
Et vous pouvez déclencher cet événement onBackPressed sous vos activités onBackPressed comme ci-dessous;
la source
getActivity().onBackPressed();
car cela invoquera l'exception: "java.lang.StackOverflowError: stack size 8MB".Ce n'est qu'un petit code qui fera l'affaire:
J'espère que cela aide quelqu'un :)
la source
Si vous utilisez EventBus, c'est probablement une solution beaucoup plus simple:
et dans votre classe d'activité, vous pouvez définir:
BackPressedMessage.java n'est qu'un objet POJO
C'est super propre et il n'y a aucun problème d'interface / implémentation.
la source
c'est ma solution:
la source
En utilisant le composant de navigation, vous pouvez le faire comme ceci :
la source
Que diriez-vous d'utiliser onDestroyView ()?
la source
i = i
ouif (1 < 0) {}
.la source
dans votre fragment, ajoutez ce qui suit, n'oubliez pas d'implémenter l'interface de mainactivity.
la source
Dans ma solution (Kotlin);
J'utilise la fonction onBackAlternative comme paramètre sur BaseActivity .
BaseActivity
J'ai une fonction pour définir onBackPressAlternative sur BaseFragment .
BaseFragment
Ensuite, mon onBackPressAlternative est prêt à être utilisé sur des fragments.
Sous-fragments
la source
N'implémentez pas la méthode ft.addToBackStack () pour que lorsque vous appuyez sur le bouton de retour, votre activité soit terminée.
la source
Suivez simplement ces étapes:
Toujours lors de l'ajout d'un fragment,
Ensuite, dans l'activité principale, remplacez
onBackPressed()
Pour gérer le bouton de retour dans votre application,
C'est ça!
la source
Dans le cycle de vie des activités, toujours le bouton de retour Android traite les transactions FragmentManager lorsque nous utilisons FragmentActivity ou AppCompatActivity.
Pour gérer le backstack, nous n'avons pas besoin de gérer son nombre de backstack ou de marquer quoi que ce soit, mais nous devons garder le focus lors de l'ajout ou du remplacement d'un fragment. Veuillez trouver les extraits suivants pour gérer les boîtiers de bouton arrière,
Ici, je n'ajouterai pas de pile de retour pour mon fragment d'accueil car c'est la page d'accueil de mon application. Si vous ajoutez addToBackStack à HomeFragment, l'application attendra pour supprimer tous les problèmes d'acactivité, puis nous obtiendrons un écran vide, donc je garde la condition suivante,
Maintenant, vous pouvez voir le fragment précédemment ajouté sur acitvity et l'application se fermera lorsque vous atteindrez HomeFragment. vous pouvez également consulter les extraits suivants.
la source
Fragment: créez un BaseFragment en plaçant une méthode:
Activité:
Votre activité se déroulera sur les fragments attachés et visibles et appellera onBackPressed () sur chacun d'entre eux et abandonnera si l'un d'eux retourne `` vrai '' (ce qui signifie qu'il a été géré, donc aucune autre action).
la source
Selon les notes de version AndroidX ,
androidx.activity 1.0.0-alpha01
est publié et introduitComponentActivity
une nouvelle classe de base de l'existantFragmentActivity
etAppCompatActivity
. Et cette version nous apporte une nouvelle fonctionnalité:Vous pouvez désormais enregistrer un
OnBackPressedCallback
viaaddOnBackPressedCallback
pour recevoir desonBackPressed()
rappels sans avoir à remplacer la méthode dans votre activité.la source
Vous pouvez enregistrer un fragment en activité pour gérer la presse arrière:
usage:
En fragment:
En activité:
la source
Il est désormais plus facile de fournir une navigation arrière personnalisée en gérant onBackPressed avec des rappels à l'intérieur du fragment.
Si vous souhaitez que l'action de retour par défaut soit basée sur une condition, vous pouvez utiliser:
la source
À l'intérieur de la méthode onCreate du fragment, ajoutez ce qui suit:
la source
Meilleure solution,
la source