2014-11-01 11 views
22

jestem aktualnie budowania aplikacji dla Androida (14 < = SDK < = 21) za pomocą jednego ActionBarActivity i więcej Fragments, takich jak ListFragment i MapFragment, które są wymieniane w pojedynczym FrameLayout widok.Fragment addToBackStack() i popBackStackImmediate() nie działa

ActionBarActivity automatycznie zastępuje/zatwierdza fragment A. Następnie, gdy użytkownik dotknie przycisku, działanie hostingu zastępuje/zatwierdza nowy fragment B. Moim celem jest, aby użytkownik mógł wrócić do fragmentu A, gdy tylko naciska przycisk powrotu.

Kod teraz.

główną działalność

public class MainActivity extends ActionBarActivity implements StopFragment.OnFragmentInteractionListener, 
    StopItemFragment.OnFragmentInteractionListener { 
... 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     fragmentManager = getFragmentManager(); 
     fragmentManager.enableDebugLogging(true); 
     ... 
     if (fragmentManager.findFragmentById(R.id.content_frame) == null) { 
      StopItemFragment list = StopItemFragment.newInstance(null); //A - extends ListFragment 
      fragmentManager.beginTransaction() 
       .replace(R.id.content_frame, list) 
       .addToBackStack(null) 
       .commit(); 
     } 
     ... 

     @Override 
     public void onFragmentInteraction(String id) { 
     selectItem(Integer.parseInt(id)); 
     } 


     private void selectItem(int position) { 
     StopFragment fragment = StopFragment.newInstance(null, null); //B - extends Fragment 
     ... 
     fragmentManager.beginTransaction() 
      .replace(R.id.content_frame, fragment) 
      .commit(); 

     ... 
     } 
} 


Problem

Nawet jeśli addToBackStack() nazywa, kiedy jestem na fragment B, nie jestem w stanie wrócić do fragmentu A. główną działalność jest bezpośrednio zamknięte. Mimo to próbowałem samodzielnie zarządzać tylnym stosem bez powodzenia. Widzę, że fragment jest na stosie, ale jeśli zadzwonię pod numer popBackStackImmediate(), fragment A zostanie wyskoczony, a transakcja fragmentu nie zostanie wykonana. (Pierwszy z powrotem prasa nic nie stało, drugi aktywność zamknięte)

Załączam również logcat FragmentManager:
http://pastebin.com/hFLHprL8

Odpowiedz

64

Dla tych, którzy nadal szukają rozwiązania.

W głównej klasie Activity (która obsługuje fragmenty) po prostu przesuń onBackPressed().

@Override 
public void onBackPressed() { 
    if (getFragmentManager().getBackStackEntryCount() > 0){ 
     getFragmentManager().popBackStack(); 
    } else { 
     super.onBackPressed(); 
    } 
} 

Nie ma onBackPressed() metoda fragmentu, a metoda ta jest tylko dla activity. Tak więc, kiedy nacisnąć klawisz wstecz, domyślne zachowanie activity pokazano, który jest

będzie albo przejść do poprzedniej aktywności (jeśli istnieje) lub aplikacja wyjdzie.

Teraz musimy zastąpić tę metodę, aby powiedzieć activity że kiedy nacisnąć klawisz wstecz, czy są jakieś fragmenty w tylnej stosie, pop je (i to jest, gdy addToBackStack() wchodzi w obraz). W przeciwnym razie postępuj zgodnie z domyślnym zachowaniem.

+2

Dziękuję. Zastanawiam się, dlaczego dokumentacja Androida nie wspomniała o tej ważnej rzeczy? Lub po prostu tęsknię za tym ... – Ryde

5

Try This (Uwaga dodać nie zastąpić dla Fragmenta i addToBackStack() dla fragmentB)

StopItemFragment list = StopItemFragment.newInstance(null); //A - extends ListFragment 
     fragmentManager.beginTransaction() 
      .add(R.id.content_frame, list) 
      .commit(); 

i

StopFragment fragment = StopFragment.newInstance(null, null); //B - extends Fragment 
    ... 
    fragmentManager.beginTransaction() 
     .replace(R.id.content_frame, fragment) 
     .addToBackStack("FragmentB") 
     .commit(); 
+1

W ten sposób mogę dodać na stos fragment B, ale nie A. FROM 'dokumentacji FragmentTransaction': ' addToBackStack(): Dodaj tę transakcję do tyłu stosu. Oznacza to, że transakcja zostanie zapamiętana po jej zatwierdzeniu i odwróci jej działanie, gdy później zostanie wyrzucony ze stosu. " – Emanuele

4

Musiałem ręcznie zadzwonić pod numer beginTransaction() i commit() z FragmentManager.
rozwiązać nadrzędnymi onBackPressed():

@Override 
public void onBackPressed() { 
    ... 
    if (fragmentManager.getBackStackEntryCount() > 1){ 
     fragmentManager.popBackStackImmediate(); 
     fragmentManager.beginTransaction().commit(); 
    } else { 
     //handle finish 
     finish(); // Closes app 
    } 
} 
1

Jeśli mają trudności z addToBackStack() & popBackStack(), a następnie po prostu użyć

FragmentTransaction ft =getSupportFragmentManager().beginTransaction(); 
ft.replace(R.id.content_frame, new HomeFragment(), "Home"); 
ft.commit();` 

W swojej działalności w OnBackPressed() dowiedzieć się fargment według tagów następnie zrobić swoje rzeczy

Fragment home = getSupportFragmentManager().findFragmentByTag("Home"); 

if (home instanceof HomeFragment && home.isVisible()) { 
    // do you stuff 
} 

Aby uzyskać więcej informacji https://github.com/DattaHujare/NavigationDrawer Nigdy nie używam metody addToBackStack() do obsługi fragmentu.

0

powodem, dla którego popBackStack() i popBackStackImmediatly() jest ze względu na fakt, że nie dodałeś tego fragmentu (który chcesz pop) do backStack. W tym celu musisz wykonać wywołanie metody addToBackStack() w momencie dokonywania transakcji, aby dodać/zastąpić fragment.

Powiązane problemy