Da diese Frage und einige der Antworten über fünf Jahre alt sind, möchte ich meine Lösung mitteilen. Dies ist eine Fortsetzung und Modernisierung der Antwort von @oyenigun
UPDATE: Am Ende dieses Artikels habe ich eine alternative Implementierung hinzugefügt, die eine abstrakte Fragment-Erweiterung verwendet, die die Aktivität überhaupt nicht mit einbezieht, was für jeden nützlich wäre, der eine komplexere Fragment-Hierarchie mit verschachtelten Fragmenten hat, die ein unterschiedliches Rückverhalten erfordern.
Ich musste dies implementieren, weil einige der Fragmente, die ich verwende, kleinere Ansichten haben, die ich mit der Zurück-Schaltfläche schließen möchte, wie z. B. kleine Informationsansichten, die aufpoppen, usw., aber dies ist gut für jeden, der das Verhalten der Zurück-Schaltfläche innerhalb von Fragmenten überschreiben muss.
Definieren Sie zunächst eine Schnittstelle
public interface Backable {
boolean onBackPressed();
}
Diese Schnittstelle, die ich als Backable
(ich bin ein Verfechter von Namenskonventionen), hat eine einzige Methode onBackPressed()
die eine boolean
Wert. Wir müssen einen booleschen Wert erzwingen, weil wir wissen müssen, ob das Drücken der Zurück-Taste das Zurück-Ereignis "absorbiert" hat. Rückgabe true
bedeutet, dass dies der Fall ist, und dass keine weiteren Maßnahmen erforderlich sind, andernfalls, false
besagt, dass die Standard-Rückholaktion immer noch stattfinden muss. Diese Schnittstelle sollte eine eigene Datei sein (vorzugsweise in einem separaten Paket namens interfaces
). Denken Sie daran, dass es eine gute Praxis ist, Ihre Klassen in Pakete aufzuteilen.
Zweitens: Finden Sie das oberste Fragment
Ich habe eine Methode erstellt, die die letzte Fragment
Objekt im hinteren Stapel. Ich verwende Tags... wenn Sie ID's verwenden, nehmen Sie die notwendigen Änderungen vor. Ich habe diese statische Methode in einer Hilfsklasse, die sich mit Navigationszuständen usw. befasst, aber natürlich können Sie sie dort unterbringen, wo es Ihnen am besten passt. Zur Veranschaulichung habe ich meine in eine Klasse namens 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;
}
Vergewissern Sie sich, dass die Anzahl der zurückliegenden Stapel größer als 0 ist, sonst wird ein ArrayOutOfBoundsException
könnte zur Laufzeit ausgelöst werden. Wenn er nicht größer als 0 ist, wird null zurückgegeben. Wir werden später auf einen Nullwert prüfen...
Drittens: Umsetzung in einem Fragment
Umsetzung der Backable
Schnittstelle in dem Fragment, in dem Sie das Verhalten der Zurück-Schaltfläche außer Kraft setzen 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;
}
}
In der onBackPressed()
überschreiben, setzen Sie die Logik, die Sie brauchen. Wenn Sie wollen, dass die Zurück-Taste no den Stapel zurücklegen (das Standardverhalten), zurückgeben wahr zurück, dass Ihr Back-Ereignis absorbiert wurde. Andernfalls wird false zurückgegeben.
Und schließlich, in Ihrer Aktivität...
Überschreiben Sie die onBackPressed()
Methode und fügen Sie ihr 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 holen uns das aktuelle Fragment im Backstack, dann führen wir eine Nullprüfung durch und stellen fest, ob es unsere Backable
Schnittstelle. Wenn ja, stellen Sie fest, ob das Ereignis absorbiert wurde. Wenn ja, sind wir fertig mit onBackPressed()
und kann zurückkehren. Andernfalls behandeln Sie es wie ein normales Zurückdrücken und rufen die Supermethode auf.
Zweite Möglichkeit, die Aktivität nicht einzubeziehen
Manchmal möchte man nicht, dass die Aktivität diese Aufgabe übernimmt, und man muss sie direkt im Fragment erledigen. Aber wer sagt, dass Sie kann nicht haben Fragmente mit einer Backpress-API? Erweitern Sie Ihr Fragment einfach um eine neue Klasse.
Erstellen Sie eine abstrakte Klasse, die Fragment erweitert und die View.OnKeyListner
Schnittstelle...
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, kann jedes Fragment, das die BackableFragment
wird automatisch die Klicks mit dem View.OnKeyListener
Schnittstelle. Rufen Sie einfach die abstrakte onBackButtonPressed()
Methode innerhalb der implementierten onKey()
Methode, bei der die Standardlogik zur Erkennung eines Drucks auf die Zurück-Taste verwendet wird. Wenn Sie andere Tastenklicks als die Rückwärtstaste registrieren müssen, müssen Sie die Methode super
Methode beim Überschreiben von onKey()
in Ihrem Fragment, sonst werden Sie Überschreiben Sie das Verhalten in der Abstraktion.
Einfach zu verwenden, 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, sobald Sie erweitern, die onBackButtonPressed()
. Sie gibt zurück void
weil es nur eine Aktion innerhalb der Fragmentklasse ausführen muss und die Absorption des Drucks nicht an die Aktivität zurückgeben muss. Vergewissern Sie sich Sie rufen die Aktivität auf onBackPressed()
Methode, wenn das, was Sie mit der Zurück-Schaltfläche tun, keine Bearbeitung erfordert, sonst wird die Zurück-Schaltfläche deaktiviert... und das wollen Sie nicht!
Vorbehalte Wie Sie sehen können, wird dadurch der Key Listener auf die Root-Ansicht des Fragments gesetzt, und wir müssen ihn fokussieren. Wenn in Ihrem Fragment, das diese Klasse erweitert (oder andere innere Fragmente oder Ansichten, die dasselbe haben), Bearbeitungstexte beteiligt sind (oder andere fokusraubende Ansichten), müssen Sie das separat behandeln. Es gibt einen guten Artikel über Erweiterung eines EditTextes den Fokus auf eine Rückenpresse zu verlieren.
Ich hoffe, jemand findet dies nützlich. Viel Spaß beim Codieren.