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
public interface Backable {
boolean onBackPressed();
}
Diese Schnittstelle, die ich aufrufe Backable
(ich bin ein Stickler für Namenskonventionen), hat eine einzige Methode onBackPressed()
, die einen boolean
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ückgeben true
bedeutet, dass dies der Fall ist und keine weitere Aktion erforderlich ist. Andernfalls muss false
die Standard-Zurückaktion weiterhin ausgeführt werden. Diese Schnittstelle sollte eine eigene Datei sein (vorzugsweise in einem separaten Paket mit dem Namen interfaces
). 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 gesetzt NavUtils
.
public static Fragment getCurrentFragment(Activity activity) {
FragmentManager fragmentManager = activity.getFragmentManager();
if (fragmentManager.getBackStackEntryCount() > 0) {
String lastFragmentName = fragmentManager.getBackStackEntryAt(
fragmentManager.getBackStackEntryCount() - 1).getName();
return fragmentManager.findFragmentByTag(lastFragmentName);
}
return null;
}
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.
public class SomeFragment extends Fragment implements
FragmentManager.OnBackStackChangedListener, Backable {
...
@Override
public boolean onBackPressed() {
// Logic here...
if (backButtonShouldNotGoBack) {
whateverMethodYouNeed();
return true;
}
return false;
}
}
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:
@Override
public void onBackPressed() {
// Get the current fragment using the method from the second step above...
Fragment currentFragment = NavUtils.getCurrentFragment(this);
// Determine whether or not this fragment implements Backable
// Do a null check just to be safe
if (currentFragment != null && currentFragment instanceof Backable) {
if (((Backable) currentFragment).onBackPressed()) {
// If the onBackPressed override in your fragment
// did absorb the back event (returned true), return
return;
} else {
// Otherwise, call the super method for the default behavior
super.onBackPressed();
}
}
// Any other logic needed...
// call super method to be sure the back button does its thing...
super.onBackPressed();
}
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 fertig onBackPressed()
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 ...
import android.app.Fragment;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
public abstract class BackableFragment extends Fragment implements View.OnKeyListener {
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.setFocusableInTouchMode(true);
view.requestFocus();
view.setOnKeyListener(this);
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
onBackButtonPressed();
return true;
}
}
return false;
}
public abstract void onBackButtonPressed();
}
Wie Sie sehen können, erfasst jedes erweiterte Fragment BackableFragment
automatisch Rückklicks über die View.OnKeyListener
Benutzeroberfläche. Rufen Sie einfach die abstrakte onBackButtonPressed()
Methode innerhalb der implementierten onKey()
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 die super
Methode beim Überschreiben onKey()
in Ihrem Fragment auf. Andernfalls wird das Verhalten in der Abstraktion überschrieben .
Einfach zu bedienen, einfach erweitern und implementieren:
public class FragmentChannels extends BackableFragment {
...
@Override
public void onBackButtonPressed() {
if (doTheThingRequiringBackButtonOverride) {
// do the thing
} else {
getActivity().onBackPressed();
}
}
...
}
Da die onBackButtonPressed()
Methode in der Superklasse abstrakt ist, müssen Sie sie implementieren, sobald Sie sie erweitern onBackButtonPressed()
. 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 aufrufen onBackPressed()
, 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.