Mam kartami Actionbar / viewpager układ z trzema zakładkami powiedzieć A , B i C . Na karcie C zakładki (fragment), dodaję inny fragment powiedzmy fragment D . z
DFragment f= new DFragment();
ft.add(android.R.id.content, f, "");
ft.remove(CFragment.this);
ft.addToBackStack(null);
ft.commit();
Modyfikuję pasek akcji w DFragment's onResume, aby dodać przycisk:
ActionBar ab = getActivity().getActionBar();
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
ab.setDisplayHomeAsUpEnabled(true);
ab.setDisplayShowHomeEnabled(true);
Teraz w DFragment, kiedy naciskam przycisk sprzętowy (telefon) Wstecz, wracam do oryginalnego układu z zakładkami (ABC) z zaznaczonym CFragment. Jak mogę osiągnąć tę funkcjonalność za pomocą przycisku Actionbar Up?
android
android-fragments
android-actionbar
SohailAziz
źródło
źródło
Odpowiedzi:
Zaimplementuj
OnBackStackChangedListener
i dodaj ten kod do swojego działania dotyczącego fragmentów.@Override public void onCreate(Bundle savedInstanceState) { //Listen for changes in the back stack getSupportFragmentManager().addOnBackStackChangedListener(this); //Handle when activity is recreated like on orientation Change shouldDisplayHomeUp(); } @Override public void onBackStackChanged() { shouldDisplayHomeUp(); } public void shouldDisplayHomeUp(){ //Enable Up button only if there are entries in the back stack boolean canGoBack = getSupportFragmentManager().getBackStackEntryCount()>0; getSupportActionBar().setDisplayHomeAsUpEnabled(canGoBack); } @Override public boolean onSupportNavigateUp() { //This method is called when the up button is pressed. Just the pop back stack. getSupportFragmentManager().popBackStack(); return true; }
źródło
onSupportNavigateUp()
: „Metoda nie zastępuje metody ze swojej nadklasy”.onOptionsItemSelected
, możesz również sprawdzić itemIdandroid.R.id.home
zamiast dodawaćonSupportNavigateUp
.ActionBar
? Nie widzę żadnego, kiedy implementuję ten kod. Mogę tylko kliknąć ikonę, ale to nic nie robi. Android 4.0+.Mam to. po prostu zastąp onOptionsItemSelected w aktywności hostingu i wyskakuje backstack, np
public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: { FragmentManager fm = getSupportFragmentManager(); if (fm.getBackStackEntryCount() > 0) { fm.popBackStack(); return true; } break; } } return super.onOptionsItemSelected(item); }
Zadzwoń
getActionBar().setDisplayHomeAsUpEnabled(boolean);
igetActionBar().setHomeButtonEnabled(boolean);
wonBackStackChanged()
jak wyjaśniono w odpowiedzi poniżej.źródło
switch
instrukcji wraz z obudowąandroid.R.id.home
.Jeśli masz jedno działanie dla rodziców i chcesz, aby ten przycisk w górę działał jako przycisk Wstecz, możesz użyć tego kodu:
dodaj to do onCreate w swojej głównej klasie aktywności
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { int stackHeight = getSupportFragmentManager().getBackStackEntryCount(); if (stackHeight > 0) { // if we have something on the stack (doesn't include the current shown fragment) getSupportActionBar().setHomeButtonEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true); } else { getSupportActionBar().setDisplayHomeAsUpEnabled(false); getSupportActionBar().setHomeButtonEnabled(false); } } });
a następnie dodaj onOptionsItemSelected w następujący sposób:
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: getSupportFragmentManager().popBackStack(); return true; .... }
Generalnie używam tego przez cały czas i wydaje się całkiem legalny
źródło
Activity
, w nadziei, że wróci do fragmentu, od którego się zaczął. Przycisk Wstecz pojawia się obok ikony mojej aplikacji, kiedy przechodzę do mojejActivity
, ale klikam ikonę i nic się nie dzieje (powinien wrócić do fragmentu). Każdy pomysł, dlaczego? Dzięki.możesz wrócić za pomocą przycisku w górę, takiego jak przycisk Wstecz;
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: super.onBackPressed(); return true; } return super.onOptionsItemSelected(item); }
źródło
Wiem, że to stare pytanie, ale może ktoś (taki jak ja) też go potrzebuje.
Jeśli Twoja aktywność rozszerza AppCompatActivity , możesz użyć prostszego (dwuetapowego) rozwiązania:
1 - Za każdym razem, gdy dodajesz fragment spoza domu, po prostu pokaż przycisk w górę, zaraz po zatwierdzeniu transakcji fragmentu. Lubię to:
// ... add a fragment // Commit the transaction transaction.commit(); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
2 - Następnie, gdy wciśnięty jest przycisk UP, ukrywasz go.
@Override public boolean onSupportNavigateUp() { getSupportActionBar().setDisplayHomeAsUpEnabled(false); return true; }
Otóż to.
źródło
Użyłem kombinacji Rogera Garzona Nieto i sohailaziza . Moja aplikacja ma jedną MainActivity i fragmenty A, B, C, które są do niej ładowane. Mój fragment „domowy” (A) implementuje OnBackStackChangedListener i sprawdza rozmiar backStack; jeśli jest mniej niż jeden, ukrywa przycisk W GÓRĘ. Fragmenty B i C zawsze ładują przycisk Wstecz (w moim projekcie B jest uruchamiany z A, a C z B). Sama MainActivity po prostu wyskakuje backstack po naciśnięciu przycisku UP i ma metody pokazania / ukrycia przycisku, który wywołują fragmenty:
Główna aktywność:
public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { // Respond to the action bar's Up/Home button case android.R.id.home: getSupportFragmentManager().popBackStack(); return true; } return super.onOptionsItemSelected(item); } public void showUpButton() { getSupportActionBar().setDisplayHomeAsUpEnabled(true); } public void hideUpButton() { getSupportActionBar().setDisplayHomeAsUpEnabled(false); }
fragmentA (implementuje FragmentManager.OnBackStackChangedListener):
public void onCreate(Bundle savedinstanceSate) { // listen to backstack changes getActivity().getSupportFragmentManager().addOnBackStackChangedListener(this); // other fragment init stuff ... } public void onBackStackChanged() { // enable Up button only if there are entries on the backstack if(getActivity().getSupportFragmentManager().getBackStackEntryCount() < 1) { ((MainActivity)getActivity()).hideUpButton(); } }
fragmentB, fragmentC:
public void onCreate(Bundle savedinstanceSate) { // show the UP button ((MainActivity)getActivity()).showUpButton(); // other fragment init stuff ... }
źródło
To zadziałało dla mnie. Zastąp na przykład onSupportNavigateUp i onBackPressed (kod w Kotlin);
override fun onBackPressed() { val count = supportFragmentManager.backStackEntryCount if (count == 0) { super.onBackPressed() } else { supportFragmentManager.popBackStack() } } override fun onSupportNavigateUp(): Boolean { super.onSupportNavigateUp() onBackPressed() return true }
Teraz we fragmencie, jeśli wyświetlisz strzałkę w górę
activity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
Kliknięcie go powoduje powrót do poprzedniej czynności.
źródło
Kotlin:
class MyActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... supportFragmentManager.addOnBackStackChangedListener { setupHomeAsUp() } setupHomeAsUp() } private fun setupHomeAsUp() { val shouldShow = 0 < supportFragmentManager.backStackEntryCount supportActionBar?.setDisplayHomeAsUpEnabled(shouldShow) } override fun onSupportNavigateUp(): Boolean = supportFragmentManager.popBackStack().run { true } ... }
źródło
To bardzo dobre i niezawodne rozwiązanie: http://vinsol.com/blog/2014/10/01/handling-back-button-press-inside-fragments/
Facet stworzył abstrakcyjny fragment, który obsługuje zachowanie backPress i przełącza się między aktywnymi fragmentami za pomocą wzorca strategii.
Dla niektórych z was może być mała wada w klasie abstrakcyjnej ...
Krótko mówiąc, rozwiązanie z linku wygląda tak:
// Abstract Fragment handling the back presses public abstract class BackHandledFragment extends Fragment { protected BackHandlerInterface backHandlerInterface; public abstract String getTagText(); public abstract boolean onBackPressed(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(!(getActivity() instanceof BackHandlerInterface)) { throw new ClassCastException("Hosting activity must implement BackHandlerInterface"); } else { backHandlerInterface = (BackHandlerInterface) getActivity(); } } @Override public void onStart() { super.onStart(); // Mark this fragment as the selected Fragment. backHandlerInterface.setSelectedFragment(this); } public interface BackHandlerInterface { public void setSelectedFragment(BackHandledFragment backHandledFragment); } }
I wykorzystanie w działalności:
// BASIC ACTIVITY CODE THAT LETS ITS FRAGMENT UTILIZE onBackPress EVENTS // IN AN ADAPTIVE AND ORGANIZED PATTERN USING BackHandledFragment public class TheActivity extends FragmentActivity implements BackHandlerInterface { private BackHandledFragment selectedFragment; @Override public void onBackPressed() { if(selectedFragment == null || !selectedFragment.onBackPressed()) { // Selected fragment did not consume the back press event. super.onBackPressed(); } } @Override public void setSelectedFragment(BackHandledFragment selectedFragment) { this.selectedFragment = selectedFragment; } }
źródło