ponieważ to pytanie i niektóre odpowiedzi mają ponad pięć lat, podzielę się moim rozwiązaniem. Jest to kontynuacja i modernizacja odpowiedzi @oyenigun
AKTUALIZACJA:
Na dole tego artykułu dodałem alternatywną implementację przy użyciu abstrakcyjnego rozszerzenia fragmentu, które w ogóle nie będzie obejmować działania, co byłoby przydatne dla każdego, kto ma bardziej złożoną hierarchię fragmentów obejmującą zagnieżdżone fragmenty, które wymagają innego zachowania wstecznego.
Musiałem to zaimplementować, ponieważ niektóre fragmenty, których używam, mają mniejsze widoki, które chciałbym odrzucić za pomocą przycisku Wstecz, takie jak małe wyskakujące widoki informacji itp., Ale jest to dobre dla każdego, kto musi zastąpić zachowanie przycisk Wstecz wewnątrz fragmentów.
Najpierw zdefiniuj interfejs
public interface Backable {
boolean onBackPressed();
}
Ten interfejs, który nazywam Backable
(jestem zwolennikiem konwencji nazewnictwa), ma jedną metodę, onBackPressed()
która musi zwrócić boolean
wartość. Musimy wymusić wartość logiczną, ponieważ będziemy musieli wiedzieć, czy naciśnięcie przycisku Wstecz „pochłonęło” zdarzenie Wstecz. Zwrot true
oznacza, że tak, i nie jest wymagane żadne dalsze działanie, w przeciwnym razie false
mówi, że nadal musi nastąpić domyślna akcja wstecz. Ten interfejs powinien być własnym plikiem (najlepiej w osobnym pakiecie o nazwie interfaces
). Pamiętaj, że dzielenie klas na pakiety to dobra praktyka.
Po drugie, znajdź górny fragment
Stworzyłem metodę, która zwraca ostatni Fragment
obiekt z tylnego stosu. Używam tagów ... jeśli używasz identyfikatorów, wprowadź niezbędne zmiany. Mam tę statyczną metodę w klasie użytkowej, która zajmuje się stanami nawigacji itp., Ale oczywiście umieść ją tam, gdzie najbardziej Ci odpowiada. Dla budowania umieściłem mój w klasie o nazwie 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;
}
Upewnij się, że liczba tylnych stosów jest większa niż 0, w przeciwnym razie ArrayOutOfBoundsException
może zostać wyrzucony w czasie wykonywania. Jeśli nie jest większa niż 0, zwróć null. Później sprawdzimy wartość zerową ...
Po trzecie, zaimplementuj we fragmencie
Zaimplementuj Backable
interfejs w dowolnym fragmencie, w którym chcesz zastąpić zachowanie przycisku Wstecz. Dodaj metodę implementacji.
public class SomeFragment extends Fragment implements
FragmentManager.OnBackStackChangedListener, Backable {
...
@Override
public boolean onBackPressed() {
// Logic here...
if (backButtonShouldNotGoBack) {
whateverMethodYouNeed();
return true;
}
return false;
}
}
W onBackPressed()
zastąpieniu wprowadź dowolną logikę. Jeśli chcesz, aby przycisk Wstecz nie wyskakiwał z tylnego stosu (zachowanie domyślne), zwróć wartość true , że zdarzenie Wstecz zostało zaabsorbowane. W przeciwnym razie zwróć false.
Wreszcie w Twojej działalności ...
Zastąp onBackPressed()
metodę i dodaj do niej tę logikę:
@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();
}
Otrzymujemy bieżący fragment na tylnym stosie, a następnie sprawdzamy zero i sprawdzamy, czy implementuje on nasz Backable
interfejs. Jeśli tak, określ, czy zdarzenie zostało wchłonięte. Jeśli tak, to koniec onBackPressed()
i możemy wrócić. W przeciwnym razie traktuj to jak normalne naciśnięcie wstecz i wywołaj metodę super.
Druga opcja nie angażowania działania
Czasami nie chcesz, aby Działanie w ogóle sobie z tym poradziło i musisz obsługiwać to bezpośrednio w tym fragmencie. Ale kto mówi, że nie możesz mieć fragmentów z interfejsem API prasy wstecznej? Po prostu rozszerz swój fragment na nową klasę.
Utwórz klasę abstrakcyjną, która rozszerza Fragment i implementuje View.OnKeyListner
interfejs ...
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();
}
Jak widać, każdy rozciągający się fragment BackableFragment
automatycznie przechwytuje kliknięcia wstecz przy użyciu View.OnKeyListener
interfejsu. Wystarczy wywołać onBackButtonPressed()
metodę abstrakcyjną z zaimplementowanej onKey()
metody, używając standardowej logiki, aby rozpoznać naciśnięcie przycisku Wstecz. Jeśli musisz zarejestrować kliknięcia klawiszy inne niż przycisk Wstecz, pamiętaj, aby wywołać super
metodę podczas zastępowaniaonKey()
fragmentu, w przeciwnym razie zastąpisz zachowanie w abstrakcji.
Prosty w użyciu, wystarczy rozszerzyć i wdrożyć:
public class FragmentChannels extends BackableFragment {
...
@Override
public void onBackButtonPressed() {
if (doTheThingRequiringBackButtonOverride) {
// do the thing
} else {
getActivity().onBackPressed();
}
}
...
}
Ponieważ onBackButtonPressed()
metoda w superklasie jest abstrakcyjna, po rozszerzeniu należy ją zaimplementować onBackButtonPressed()
. Zwraca, void
ponieważ po prostu musi wykonać akcję w klasie fragmentów i nie musi przekazywać absorpcji prasy z powrotem do działania. Upewnij się, że wywołujesz onBackPressed()
metodę Activity , jeśli cokolwiek robisz z przyciskiem Wstecz nie wymaga obsługi, w przeciwnym razie przycisk Wstecz zostanie wyłączony ... i nie chcesz tego!
Ostrzeżenia
Jak widać, ustawia to kluczowy odbiornik w widoku głównym fragmentu i będziemy musieli go skoncentrować. Jeśli w twoim fragmencie, który rozszerza tę klasę (lub inne wewnętrzne fragmenty lub widoki, które mają to samo), zaangażujesz w tekst fragmenty (lub inne widoki kradnące fokus), musisz poradzić sobie z tym osobno. Jest dobry artykuł o rozszerzaniu EditText, aby stracić skupienie na prasie wstecznej.
Mam nadzieję, że ktoś uzna to za przydatne. Szczęśliwego kodowania.