A livello di codice, tornare al frammento precedente nel backstack


218

Supponiamo che io abbia un'attività con frammenti aggiunti a livello di codice:

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

Qual è il modo migliore per tornare al frammento precedente che era visibile?

Ho trovato la funzionalità Trigger back-button al clic sul pulsante in Android, ma sto pensando che simulare un evento back key non sia il modo giusto di procedere (e non riesco nemmeno a farlo funzionare):

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

Chiamare finish()chiude semplicemente l'attività che non mi interessa.

C'è un modo migliore per farlo?

Risposte:


354

Guarda i getFragmentManager().popBackStack()metodi (ce ne sono diversi tra cui scegliere)

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


91
getFragmentManager().popBackStackImmediate();ha fatto il trucco. Grazie.
Aske B.

1
Ma dove metterei questo metodo? Nel mio listener tab?
rasen58,

1
senza vedere il codice, è difficile dirlo ... ma dovrebbe andare nella sezione del codice che viene eseguita quando si desidera "chiudere" il frammento corrente e tornare al frammento precedente.
Stuckless

1
che dire di getSupportFragmentManager ()
ViliusK

5
Non dimenticare di aggiungere "addToBackStack (" tag ")" nel tuo codice. "fragmentManager.beginTransaction () sostituire (R.id.content_frame, frammento) .addToBackStack (" tag ") commit ();". se scrivi addToBackStack (null), lo gestirà da solo ma se dai un tag, dovresti gestirlo manualmente.
Khaled Saif l'

129

Per approfondire le altre risposte fornite, questa è la mia soluzione (inserita in un'attività):

@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();  
    }
}

5
e perché succede? Nell'esempio di frammento developer.android.com/training/basics/fragments/index.html non stanno ignorando l'evento onbackpressed e tuttavia sono in grado di eseguire il backstack del frammento. Ho usato trasaction.addToBackStack (null); ma non succede nulla. Puoi spiegare perché?
Murtaza Khursheed Hussain,

@MurtazaHussain dovresti probabilmente fare una nuova domanda se vuoi aiuto con questo. È un po 'difficile vedere cosa sta succedendo senza guardare più codice.
Kyle Falconer,

2
Nel mio caso, ho dovuto fare fm.getBackStackEntryCount() > 1per richiamare l'attività quando nello stack è presente solo il primo frammento.
Facundo Olano,

3
Android lo fa già per te: "Quando ci sono oggetti FragmentTransaction nello stack posteriore e l'utente preme il pulsante Indietro, FragmentManager estrae la transazione più recente dallo stack posteriore ed esegue l'azione inversa (come rimuovere un frammento se la transazione aggiunto). " (Fonte)
artkoenig,

29

Quando stiamo aggiornando / aggiungendo i frammenti,

Dovrebbe includere il .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();

Dopodiché, se diamo il valore getFragments.popBackStackImmediate()restituirà vero se aggiungiamo / aggiorniamo i frammenti e torniamo alla schermata corrente.


7

Aggiungi quella riga al tuo metodo onBackPressed (). Il metodo popBackStackImmediate () ti riporterà al frammento precedente se hai qualche frammento nello stack posteriore `

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

`


5

Questa soluzione funziona perfettamente per la navigazione dei frammenti basata sulla barra inferiore quando si desidera chiudere l'app quando si preme nuovamente nel frammento primario.

D'altra parte, quando si apre il frammento secondario (frammento in frammento) che nel mio codice è definito "DettagliatoPizza", verrà restituito lo stato precedente del frammento primario. Saluti !

All'interno delle attività sul retro premuto metti questo:

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);
}

E lancia l'altro frammento in questo modo:

Fragment someFragment = new FragmentDetailedPizza();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.container_body, someFragment, "DetailedPizza");
transaction.addToBackStack("DetailedPizza");
transaction.commit();

4

Queste risposte non funzionano se non ho aggiunto addToBackStack () aggiunto alla mia transazione di frammenti, ma puoi usare:

getActivity().onBackPressed();

dal tuo frammento per tornare indietro di un passo;


1

A livello di codice, tornare al frammento precedente usando il seguente codice.

if ( getFragmentManager().getBackStackEntryCount() > 0) 
{
          getFragmentManager().popBackStack();
          return;
}
super.onBackPressed();

1

Per far tornare quel frammento, aggiungi quel frammento al backstack su cui vuoi tornare premuto, ad esempio:

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();
        }
    }
});

Nel caso sopra, sto aprendo LoginFragmentquando Button buttonviene premuto, in questo momento l'utente è dentro SignupFragment. Quindi, se addToBackStack(TAG)viene chiamato, dove TAG = "SignupFragment", quindi quando viene premuto il pulsante Indietro LoginFragment, torniamo a SignUpFragment.

Buona programmazione!


Penso che TAG non influisca, forse anche null.
CoolMind,

1

Aggiungendo fragment_tran.addToBackStack(null)l'ultimo frammento, sono in grado di tornare sull'ultimo frammento.

aggiungendo un nuovo frammento :

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();
        }
    });

1

Sono venuto qui cercando o la stessa idea, e nel frattempo mi è venuta in mente la mia, che credo non sia poi così male e funziona se con ViewPager.

Quindi, quello che ho fatto, è quello di sovrascrivere il metodo onBackPressed nell'attività padre che contiene viewPager e impostarlo per tornare sempre meno 1 posizione fino a raggiungere il primo frammento, quindi chiudere l'attività.

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

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

Questo potrebbe avere degli inconvenienti, come se ogni volta risalisse solo in un modo, quindi potrebbe non funzionare alla grande se ci sono delle schede e cambi posizione con frammenti saltati, (andando da 0 a 2, e poi premendo indietro ti metterebbe su 1, anziché 0)

Per il mio caso, con 2 frammenti in viewPager senza schede, fa bene il lavoro.


Una domanda simile ha già ricevuto risposta. stackoverflow.com/questions/10863572/...
AtifSayings

0

Prova sotto il codice:

@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();
            }
        }
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.