Gibt es eine Möglichkeit, wie wir onBackPressed()
in Android Fragment implementieren können, ähnlich wie wir es in Android Activity implementieren?
Da haben die Fragment Lebenszyklus nicht onBackPressed()
. Gibt es eine andere alternative Methode, um onBackPressed()
Android 3.0-Fragmente zu überschreiben?
android
android-fragments
onbackpressed
Android_programmer_camera
quelle
quelle
Antworten:
Ich habe auf diese Weise das Überschreiben
onBackPressed
in der Aktivität gelöst . AlleFragmentTransaction
sindaddToBackStack
vor dem Festschreiben:quelle
Meiner Meinung nach ist die beste Lösung:
JAVA-LÖSUNG
Erstellen Sie eine einfache Schnittstelle:
Und in deiner Aktivität
Endlich in deinem Fragment:
KOTLIN-LÖSUNG
1 - Schnittstelle erstellen
2 - Bereiten Sie Ihre Aktivität vor
3 - Implementieren Sie in Ihrem Zielfragment
quelle
R.id.main_container
? Ist das die ID für den FragmentPager?.?
) und das Erzwingen von Nicht-Nullen (!!
) zu NPEs führen - die Umwandlung ist nicht immer sicher. Ich würde lieber schreibenif ((fragment as? IOnBackPressed)?.onBackPressed()?.not() == true) { ... }
oder mehr kotliney(fragment as? IOnBackPressed)?.onBackPressed()?.not()?.let { ... }
.onBackPressed()?.takeIf { !it }?.let{...}
?.not()
gibt nur die Umkehrung zurück.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() }
Dies ist für Leute, die Kotlin und NavigationControllerLaut @HaMMeRed ist die Antwort hier Pseudocode, wie es funktionieren soll. Nehmen wir an, Ihre Hauptaktivität heißt
BaseActivity
untergeordnete Fragmente (wie im Beispiel SlidingMenu lib). Hier sind die Schritte:Zuerst müssen wir eine Schnittstelle und eine Klasse erstellen, die ihre Schnittstelle implementiert, um eine generische Methode zu haben
Klassenschnittstelle erstellen
OnBackPressedListener
Erstellen Sie eine Klasse, die Fähigkeiten von implementiert
OnBackPressedListener
Seitdem werden wir an unserem Code
BaseActivity
und seinen Fragmenten arbeitenErstellen Sie einen privaten Listener über Ihrer Klasse
BaseActivity
Methode zum Einstellen des Listeners erstellen
BaseActivity
in override so
onBackPressed
etwas implementierenIn Ihrem Fragment in
onCreateView
sollten Sie unseren Listener hinzufügenVoila, wenn Sie jetzt in Fragment zurückklicken, sollten Sie Ihre benutzerdefinierte On-Back-Methode abfangen.
quelle
onBackPressed()
welchem Fragment angezeigt wurde, als die Zurück-Taste gedrückt wurde?((BaseActivity)activity).setOnBackPressedListener(new OnBackpressedListener(){ public void doBack() { //...your stuff here }});
Dies hat bei mir funktioniert: https://stackoverflow.com/a/27145007/3934111
quelle
Wenn Sie diese Art von Funktionalität wünschen, müssen Sie sie in Ihrer Aktivität überschreiben und dann
YourBackPressed
allen Ihren Fragmenten eine Schnittstelle hinzufügen , die Sie bei jedem Drücken der Zurück-Taste auf das entsprechende Fragment aufrufen.Bearbeiten: Ich möchte meine vorherige Antwort anhängen.
Wenn ich dies heute tun würde, würde ich eine Sendung oder möglicherweise eine bestellte Sendung verwenden, wenn ich erwarten würde, dass andere Panels im Einklang mit dem Master- / Hauptinhaltspanel aktualisiert werden.
LocalBroadcastManager
in der Support-Bibliothek kann dabei helfen, und Sie senden einfach die Sendung einonBackPressed
und abonnieren Ihre Fragmente, die Sie interessieren. Ich denke, dass Messaging eine entkoppelte Implementierung ist und besser skaliert werden kann, daher wäre es jetzt meine offizielle Implementierungsempfehlung. Verwenden Sie einfach dieIntent
Aktion von 'als Filter für Ihre Nachricht. Senden Sie Ihre neu erstelltenACTION_BACK_PRESSED
, senden Sie sie aus Ihrer Aktivität und warten Sie in den entsprechenden Fragmenten darauf.quelle
LocalBroadcastManager
bestellte Sendungen nicht möglich sindNichts davon ist einfach zu implementieren und funktioniert auch nicht optimal.
Fragmente haben einen Methodenaufruf onDetach, der die Arbeit erledigt.
Dies wird den Job machen.
quelle
isRemoving()
wie unter stackoverflow.com/a/27103891/2914140 beschrieben hinzuzufügen .Wenn Sie
androidx.appcompat:appcompat:1.1.0
oder höher verwenden, können SieOnBackPressedCallback
Ihrem Fragment wie folgt ein hinzufügenSiehe https://developer.android.com/guide/navigation/navigation-custom-back
quelle
androidx-core-ktx
, können Sie verwendenrequireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { /* code to be executed when back is pressed */ }
LifecycleOwner
Parameter wie in diesem Beispiel hinzugefügt werden sollte. Ohne sie werden alle danach gestarteten Fragmente aufgerufen,handleBackPressed()
wenn die Zurück-Taste gedrückt wird.Fügen
addToBackStack
Sie einfach Folgendes hinzu, während Sie zwischen Ihren Fragmenten wechseln:Wenn Sie schreiben
addToBackStack(null)
, wird es von selbst behandelt, aber wenn Sie ein Tag geben, sollten Sie es manuell behandeln.quelle
Da diese Frage und einige der Antworten älter als fünf Jahre sind, möchte ich meine Lösung mitteilen. Dies ist eine Fortsetzung und Modernisierung der Antwort von @oyenigun
AKTUALISIEREN: Am Ende dieses Artikels habe ich eine alternative Implementierung hinzugefügt, die eine abstrakte Fragmenterweiterung verwendet, die die Aktivität überhaupt nicht einbezieht. Dies ist nützlich für alle Benutzer mit einer komplexeren Fragmenthierarchie, die verschachtelte Fragmente umfasst, die ein anderes Back-Verhalten erfordern.
Ich musste dies implementieren, da einige der von mir verwendeten Fragmente kleinere Ansichten haben, die ich mit der Schaltfläche "Zurück" schließen möchte, z. B. kleine Informationsansichten, die angezeigt werden usw. Dies ist jedoch gut für alle, die das Verhalten von überschreiben müssen der Zurück-Knopf in Fragmenten.
Definieren Sie zunächst eine Schnittstelle
Diese Schnittstelle, die ich aufrufe
Backable
(ich bin ein Stickler für Namenskonventionen), hat eine einzige MethodeonBackPressed()
, die einenboolean
Wert zurückgeben muss. Wir müssen einen booleschen Wert erzwingen, da wir wissen müssen, ob das Drücken der Zurück-Taste das Back-Ereignis "absorbiert" hat. Zurückgebentrue
bedeutet, dass dies der Fall ist und keine weitere Aktion erforderlich ist. Andernfalls mussfalse
die Standard-Zurückaktion weiterhin ausgeführt werden. Diese Schnittstelle sollte eine eigene Datei sein (vorzugsweise in einem separaten Paket mit dem Nameninterfaces
). Denken Sie daran, dass es eine gute Praxis ist, Ihre Klassen in Pakete zu unterteilen.Zweitens finden Sie das obere Fragment
Ich habe eine Methode erstellt, die das letzte
Fragment
Objekt im Backstack zurückgibt. Ich verwende Tags ... Wenn Sie IDs verwenden, nehmen Sie die erforderlichen Änderungen vor. Ich habe diese statische Methode in einer Utility-Klasse, die sich mit Navigationszuständen usw. befasst, aber natürlich platzieren Sie sie dort, wo sie am besten zu Ihnen passt. Zur Erbauung habe ich meine in eine Klasse namens gesetztNavUtils
.Stellen Sie sicher, dass die Anzahl der Backstacks größer als 0 ist, da dies sonst
ArrayOutOfBoundsException
zur Laufzeit ausgelöst werden kann. Wenn es nicht größer als 0 ist, geben Sie null zurück. Wir werden später nach einem Nullwert suchen ...Drittens in einem Fragment implementieren
Implementieren Sie die
Backable
Schnittstelle in dem Fragment, in dem Sie das Verhalten der Zurück-Schaltfläche überschreiben müssen. Fügen Sie die Implementierungsmethode hinzu.onBackPressed()
Geben Sie beim Überschreiben die gewünschte Logik ein. Wenn Sie möchten, dass die Zurück-Schaltfläche den Back-Stack nicht öffnet (Standardverhalten), geben Sie true zurück , damit Ihr Back-Ereignis absorbiert wurde. Andernfalls geben Sie false zurück.Zuletzt in Ihrer Aktivität ...
Überschreiben Sie die
onBackPressed()
Methode und fügen Sie diese Logik hinzu:Wir erhalten das aktuelle Fragment im Backstack, führen dann eine Nullprüfung durch und stellen fest, ob es unsere
Backable
Schnittstelle implementiert . Wenn dies der Fall ist, stellen Sie fest, ob das Ereignis absorbiert wurde. Wenn ja, sind wir fertigonBackPressed()
und können zurückkehren. Andernfalls behandeln Sie es als normales Zurückdrücken und rufen Sie die Supermethode auf.Zweite Option, die Aktivität nicht einzubeziehen
Manchmal möchten Sie nicht, dass die Aktivität dies überhaupt behandelt, und Sie müssen sie direkt innerhalb des Fragments behandeln. Aber wer sagt, dass Sie keine Fragmente mit einer Backpress-API haben können? Erweitern Sie einfach Ihr Fragment auf eine neue Klasse.
Erstellen Sie eine abstrakte Klasse, die Fragment erweitert und die
View.OnKeyListner
Schnittstelle implementiert ...Wie Sie sehen können, erfasst jedes erweiterte Fragment
BackableFragment
automatisch Rückklicks über dieView.OnKeyListener
Benutzeroberfläche. Rufen Sie einfach die abstrakteonBackButtonPressed()
Methode innerhalb der implementiertenonKey()
Methode mit der Standardlogik auf, um einen Zurück-Tastendruck zu erkennen. Wenn Sie andere Tastenklicks als die Schaltfläche "Zurück" registrieren müssen, rufen Sie diesuper
Methode beim ÜberschreibenonKey()
in Ihrem Fragment auf. Andernfalls wird das Verhalten in der Abstraktion überschrieben .Einfach zu bedienen, einfach erweitern und implementieren:
Da die
onBackButtonPressed()
Methode in der Superklasse abstrakt ist, müssen Sie sie implementieren, sobald Sie sie erweiternonBackButtonPressed()
. Es kehrt zurück,void
weil es nur eine Aktion innerhalb der Fragmentklasse ausführen muss und die Absorption der Presse nicht an die Aktivität zurücksenden muss. Stellen Sie sicher, dass Sie die Aktivitätsmethode aufrufenonBackPressed()
, wenn für alles, was Sie mit der Zurück-Schaltfläche tun, keine Behandlung erforderlich ist. Andernfalls wird die Zurück-Schaltfläche deaktiviert ... und das möchten Sie nicht!Vorsichtsmaßnahmen Wie Sie sehen können, wird der Key Listener auf die Stammansicht des Fragments gesetzt, und wir müssen es fokussieren. Wenn in Ihrem Fragment Bearbeitungstexte (oder andere Ansichten, die den Fokus stehlen) enthalten sind, die diese Klasse erweitern (oder andere innere Fragmente oder Ansichten, die dieselbe haben), müssen Sie dies separat behandeln. Es gibt einen guten Artikel über die Erweiterung eines EditText , um den Fokus auf ein Zurückdrücken zu verlieren.
Ich hoffe, jemand findet das nützlich. Viel Spaß beim Codieren.
quelle
super.onBackPressed();
zweimal anrufen ?currentFragment
. Wenn das Fragment nicht null ist und das Fragment dieBackable
Schnittstelle implementiert , wird keine Aktion ausgeführt. Wenn das Fragment nicht null ist und NICHT implementiert wirdBackable
, rufen wir die Super-Methode auf. Wenn das Fragment null ist, springt es zum letzten Superaufruf.currentFragment
nicht null ist und eine Instanz von Backable ist und getrennt wird (wir haben dieback
Taste gedrückt und das Fragment geschlossen), wird das erste Vorkommen vonsuper.onBackPressed();
aufgerufen, dann das zweite.Die Lösung ist einfach:
1) Wenn Sie eine Basisfragmentklasse haben, die alle Fragmente erweitern, fügen Sie diesen Code zu ihrer Klasse hinzu, andernfalls erstellen Sie eine solche Basisfragmentklasse
2) Überschreiben Sie in Ihrer Aktivitätsklasse onBackPressed wie folgt:
3) Fügen Sie in Ihrer Fragment-Klasse den gewünschten Code hinzu:
quelle
onBackPressed()
bewirkt, dass sich das Fragment von der Aktivität löst.Laut der Antwort von @Sterling Diaz denke ich, dass er Recht hat. ABER eine Situation wird falsch sein. (zB Bildschirm drehen)
Ich denke also, wir könnten herausfinden, ob wir
isRemoving()
Ziele erreichen sollen.Sie können es bei
onDetach()
oder schreibenonDestroyView()
. Es ist Arbeit.quelle
Nun, ich habe es so gemacht und es funktioniert für mich
Einfache Schnittstelle
FragmentOnBackClickInterface.java
Beispielimplementierung
MyFragment.java
dann überschreiben Sie einfach onBackPressed in Aktivität
quelle
Sie sollten Ihrem Projekt eine Schnittstelle wie unten hinzufügen.
Und dann sollten Sie diese Schnittstelle auf Ihrem Fragment implementieren.
Und Sie können dieses onBackPressed-Ereignis unter Ihren Aktivitäten onBackPressed-Ereignis wie unten auslösen.
quelle
getActivity().onBackPressed();
Sie nicht auf, da dies die Ausnahme "java.lang.StackOverflowError: Stapelgröße 8 MB" auslöst.Dies ist nur ein kleiner Code, der den Trick macht:
Hoffe es hilft jemandem :)
quelle
Wenn Sie EventBus verwenden, ist dies wahrscheinlich eine weitaus einfachere Lösung:
und in Ihrer Aktivitätsklasse können Sie Folgendes definieren:
BackPressedMessage.java ist nur ein POJO-Objekt
Dies ist super sauber und es gibt keine Probleme mit der Schnittstelle / Implementierung.
quelle
Das ist meine Lösung:
quelle
Mit der Navigationskomponente können Sie dies folgendermaßen tun :
quelle
Wie wäre es mit onDestroyView ()?
quelle
i = i
oderif (1 < 0) {}
.quelle
Fügen Sie in Ihrem Fragment Folgendes hinzu. Vergessen Sie nicht, die Schnittstelle von mainactivity zu implementieren.
quelle
In meiner Lösung (Kotlin);
Ich verwende die Funktion onBackAlternative als Parameter für BaseActivity .
BaseActivity
Ich habe eine Funktion zum Setzen von onBackPressAlternative auf BaseFragment .
BaseFragment
Dann kann mein onBackPressAlternative für Fragmente verwendet werden.
Unterfragmente
quelle
Implementieren Sie die Methode ft.addToBackStack () nicht, damit Ihre Aktivität beendet wird, wenn Sie die Zurück-Taste drücken.
quelle
Befolgen Sie einfach diese Schritte:
Immer beim Hinzufügen eines Fragments,
Überschreiben Sie dann in der Hauptaktivität
onBackPressed()
Um die Zurück-Schaltfläche in Ihrer App zu handhaben,
Das ist es!
quelle
Im Aktivitätslebenszyklus behandelt die Android-Schaltfläche "Zurück" immer FragmentManager-Transaktionen, wenn FragmentActivity oder AppCompatActivity verwendet werden.
Um den Backstack zu handhaben, müssen wir nicht die Anzahl der Backstacks behandeln oder irgendetwas markieren, aber wir sollten den Fokus behalten, während wir ein Fragment hinzufügen oder ersetzen. Hier finden Sie die folgenden Ausschnitte, um die Fälle mit den Zurück-Tasten zu behandeln:
Hier füge ich keinen Backstack für mein Home-Fragment hinzu, da es sich um die Homepage meiner Anwendung handelt. Wenn Sie addToBackStack zu HomeFragment hinzufügen, wartet die App darauf, alle Framente in der Aktivität zu entfernen. Dann wird ein leerer Bildschirm angezeigt, sodass ich die folgende Bedingung behalte:
Jetzt können Sie das zuvor hinzugefügte Fragment auf acitvity sehen und die App wird beendet, wenn Sie HomeFragment erreichen. Sie können sich auch die folgenden Schnipsel ansehen.
quelle
Fragment: Erstellen Sie ein BaseFragment, indem Sie eine Methode platzieren:
Aktivität:
Ihre Aktivität wird über die angehängten und sichtbaren Fragmente ausgeführt und ruft onBackPressed () für jedes von ihnen auf und bricht ab, wenn eines von ihnen 'true' zurückgibt (was bedeutet, dass es behandelt wurde, also keine weiteren Aktionen).
quelle
Nach dem AndroidX Release Notes ,
androidx.activity 1.0.0-alpha01
wird freigegeben und führtComponentActivity
eine neue Basisklasse der bestehendenFragmentActivity
undAppCompatActivity
. Und diese Version bringt uns eine neue Funktion:Sie können jetzt ein
OnBackPressedCallback
Via registrierenaddOnBackPressedCallback
, umonBackPressed()
Rückrufe zu erhalten, ohne die Methode in Ihrer Aktivität überschreiben zu müssen.quelle
Sie können Fragmente in Aktivitäten registrieren, um das Zurückdrücken zu handhaben:
Verwendungszweck:
Im Fragment:
In Aktivität:
quelle
Das Bereitstellen einer benutzerdefinierten Rückennavigation durch Handling von onBackPressed ist jetzt mit Rückrufen innerhalb des Fragments einfacher.
Wenn Sie die Standard-Rückaktion basierend auf einer bestimmten Bedingung möchten, können Sie Folgendes verwenden:
quelle
Fügen Sie in der onCreate-Methode des Fragments Folgendes hinzu:
quelle
Beste Lösung,
quelle