Programowo wróć do poprzedniego fragmentu w backstacku

218

Powiedzmy, że mam aktywność, która ma fragmenty dodane programowo:

private void animateToFragment(Fragment newFragment, String tag) {
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.replace(R.id.fragment_container, newFragment, tag);
    ft.addToBackStack(null);
    ft.commit();
}

Jaki jest najlepszy sposób powrotu do poprzedniego fragmentu, który był widoczny?

Znalazłem funkcjonalność przycisku powrotu Trigger po kliknięciu przycisku w Androidzie, ale myślę, że symulowanie zdarzenia klawisza wstecz nie jest właściwym sposobem na obejście go (i nie mogę go również uruchomić):

dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));

Dzwonienie finish()tylko zamyka aktywność, która mnie nie interesuje.

Czy jest lepszy sposób, aby to zrobić?

Aske B.
źródło

Odpowiedzi:

354

Spójrz na getFragmentManager().popBackStack()metody (jest kilka do wyboru)

http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack ()

ślepy
źródło
91
getFragmentManager().popBackStackImmediate();wykonał lewę. Dzięki.
Aske B.
1
Gdzie jednak mam umieścić tę metodę? W moim czytniku kart?
rasen58
1
nie widząc kodu, trudno powiedzieć ... ale powinien przejść do części kodu, która jest wykonywana, gdy chcesz „zamknąć” bieżący fragment i powrócić do poprzedniego.
stuckless
1
co z getSupportFragmentManager ()
ViliusK 10.04.13
5
Nie zapomnij dodać do kodu „addToBackStack („ tag ”)”. „fragmentManager.beginTransaction (). replace (R.id.content_frame, fragment) .addToBackStack („ tag ”). commit ();” jeśli napiszesz addToBackStack (null), obsłuży go sam, ale jeśli podasz tag, powinieneś obsłużyć go ręcznie.
Khaled Saif,
129

Aby rozwinąć pozostałe odpowiedzi, oto moje rozwiązanie (umieszczone w działaniu):

@Override
public void onBackPressed(){
    FragmentManager fm = getFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        Log.i("MainActivity", "popping backstack");
        fm.popBackStack();
    } else {
        Log.i("MainActivity", "nothing on backstack, calling super");
        super.onBackPressed();  
    }
}
Kyle Falconer
źródło
5
i dlaczego tak się dzieje. W przykładzie fragmentu developer.android.com/training/basics/fragments/index.html nie nadpisują zdarzenia z wypisaniem wstecznym, a jednak są w stanie wycofać fragment. Użyłem trasaction.addToBackStack (null); ale nic się nie dzieje. Czy możesz mi wytłumaczyć dlaczego ?
Murtaza Khursheed Hussain
@MurtazaHussain powinieneś prawdopodobnie zadać nowe pytanie, jeśli chcesz w tym pomóc. Trochę trudno jest zobaczyć, co się dzieje, nie patrząc na więcej kodu.
Kyle Falconer
2
W moim przypadku musiałem to zrobić fm.getBackStackEntryCount() > 1, aby wywołać działanie z powrotem, gdy na stosie znajduje się tylko pierwszy fragment.
Facundo Olano
3
Android już to dla Ciebie robi: „Gdy na tylnym stosie znajdują się obiekty FragmentTransaction, a użytkownik naciska przycisk Wstecz, FragmentManager wyskakuje z ostatniej stosu z ostatniej transakcji i wykonuje akcję odwrotną (np. Usuwa fragment, jeśli transakcja dodał)). ” (Źródło)
artkoenig
29

Kiedy aktualizujemy / dodajemy fragmenty,

Powinien zawierać .addToBackStack().

getSupportFragmentManager().beginTransaction()
    .add(detailFragment, "detail") // Add this transaction to the back stack (name is an optional name for this back stack state, or null).
    .addToBackStack(null)
    .commit();

Następnie, jeśli damy getFragments.popBackStackImmediate(), zwróci wartość true, jeśli dodamy / zaktualizujemy fragmenty i wrócimy do bieżącego ekranu.

Jabeer
źródło
7

Dodaj te linie do metody onBackPressed (). Metoda popBackStackImmediate () przeniesie Cię z powrotem do poprzedniego fragmentu, jeśli masz jakiś fragment na tylnym stosie `

if(getFragmentManager().getBackStackEntryCount() > 0){
     getFragmentManager().popBackStackImmediate();
}
else{
    super.onBackPressed();
}

`

Avijit Biswas
źródło
5

To rozwiązanie działa idealnie w przypadku nawigacji po fragmentach na dolnym pasku, gdy chcesz zamknąć aplikację po ponownym naciśnięciu fragmentu głównego.

Z drugiej strony, gdy otwierasz fragment pomocniczy (fragment w fragmencie), który jest zdefiniowany jako „DetailPizza” w moim kodzie, zwróci poprzedni stan fragmentu podstawowego. Twoje zdrowie !

Wewnątrz działań na plecach wciśnij to:

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

if (home instanceof FragmentDetailedPizza && home.isVisible()) {
    if (getFragmentManager().getBackStackEntryCount() != 0) {
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
} else {
    //Primary fragment
    moveTaskToBack(true);
}

I uruchom inny fragment w ten sposób:

Fragment someFragment = new FragmentDetailedPizza();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.container_body, someFragment, "DetailedPizza");
transaction.addToBackStack("DetailedPizza");
transaction.commit();
Giedrius Šlikas
źródło
3

Te odpowiedzi nie działają, jeśli nie dodałem metody addToBackStack () do mojej transakcji fragmentu, ale możesz użyć:

getActivity().onBackPressed();

z dowolnego fragmentu, aby cofnąć się o jeden krok;

Biplob Das
źródło
1

Programowo wróć do poprzedniego fragmentu, używając następującego kodu.

if ( getFragmentManager().getBackStackEntryCount() > 0) 
{
          getFragmentManager().popBackStack();
          return;
}
super.onBackPressed();
Piyush MandaliYa
źródło
1

Aby ten fragment pojawił się ponownie, po prostu dodaj ten fragment do plecaka, który chcesz ponownie nacisnąć, np .:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Fragment fragment = new LoginFragment();
        //replacing the fragment
        if (fragment != null) {
            FragmentTransaction ft = ((FragmentActivity)getContext()).getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.content_frame, fragment);
            ft.addToBackStack("SignupFragment");
            ft.commit();
        }
    }
});

W powyższym przypadku otwieram się LoginFragmentpo Button buttonnaciśnięciu, w tej chwili użytkownik jest włączony SignupFragment. Więc jeśli addToBackStack(TAG)zostanie wywołane, gdzie TAG = "SignupFragment", to kiedy przycisk Wstecz zostanie wciśnięty LoginFragment, wrócimy do SignUpFragment.

Happy Coding!

Saurabh Singh
źródło
Myślę, że TAG nie ma wpływu, może nawet zerowy.
CoolMind
1

Dodając fragment_tran.addToBackStack(null)ostatni fragment, mogę wrócić do ostatniego fragmentu.

dodawanie nowego fragmentu :

view.findViewById(R.id.changepass).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.container, new ChangePassword());
            transaction.addToBackStack(null);
            transaction.commit();
        }
    });
Baljinder Maan
źródło
1

Przyszedłem tutaj, szukając tego samego, a tymczasem wpadłem na własny pomysł, który moim zdaniem nie jest taki zły i działa, jeśli działa z ViewPager.

Więc to, co zrobiłem, to przesłonić metodę onBackPressed w działaniu nadrzędnym, które przechowuje viewPager, i ustawić, aby zawsze cofała się o 1 pozycję do momentu osiągnięcia pierwszego fragmentu, a następnie zamyka działanie.

@Override
public void onBackPressed() {
    if(viewPager.getCurrentItem()>0){
        viewPager.setCurrentItem(viewPager.getCurrentItem()-1);
    } else {
        super.onBackPressed();
        this.close();
    }
}

private void close(){
    this.finish();
}

Może to mieć spadki, jak za każdym razem, gdy wraca tylko o jedną stronę w lewo, więc może nie działać świetnie, jeśli są tabulatory i zmieniasz pozycje z pominiętymi fragmentami (przejście od 0 do 2, a następnie naciśnięcie wstecz spowoduje włączenie 1 zamiast 0)

W moim przypadku, z 2 fragmentami w viewPager bez zakładek, robi to dobrze.

Grzesiek Eman
źródło
Podobne pytanie jest już udzielone. stackoverflow.com/questions/10863572/…
AtifSayings
0

Wypróbuj poniższy kod:

@Override
    public void onBackPressed() {
        Fragment myFragment = getSupportFragmentManager().findFragmentById(R.id.container);
        if (myFragment != null && myFragment instanceof StepOneFragment) {
            finish();
        } else {
            if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
                getSupportFragmentManager().popBackStack();
            } else {
                super.onBackPressed();
            }
        }
    }
adarsh
źródło