2014-05-19 10 views
14

Nessuna delle altre domande che ho letto su StackOverflow è stata in grado di aiutare con il mio problema. Per quanto posso dire, sto facendo tutto correttamente.App di chiusura pulsante posteriore anche quando si utilizza FragmentTransaction.addToBackStack()

Ho un flusso principale/dettaglio con frammenti.

Alla creazione dell'attività principale, il frammento maestro è caricato con il codice seguente:

Fragment frag; 
    frag = new MainListFragment();//<-- **the master fragment** 

    FragmentManager fm = getFragmentManager(); 
    FragmentTransaction transaction = fm.beginTransaction(); 
    transaction.replace(R.id.fragment_container, frag); 
    Log.d("My Debug Bitches", "stack:" + fm.getBackStackEntryCount()); 
    transaction.commit(); 

Il frammento principale ha un ListView; Cliccando su un elemento dell'elenco porta in primo piano i dettagli frammentano in questo modo:

@Override 
public void onListItemClick(ListView listView, View view, int position, long id) { 
    super.onListItemClick(listView, view, position, id); 


    FragmentManager fm = getFragmentManager(); 
    FragmentTransaction transaction = fm.beginTransaction(); 
    SubListFragment frag = new SubListFragment();//<-- **the detail fragment** 

    transaction.replace(R.id.fragment_container, frag); 
    transaction.addToBackStack(null); 
    transaction.commit(); 
    fm.executePendingTransactions(); 
    Log.d("My Debug Bitches", "stack:" + fm.getBackStackEntryCount()); 

} 

Ora, secondo LogCat, i BackStackEntryCountmodifiche 0-1 dopo naviga da maestro frammento del dettaglio frammento: enter image description here

Quindi, perché quando clicco sul pulsante Indietro mentre sono nel frammento di dettagli, l'app si chiude invece di tornare al frammento principale ??????????

risposta

54

È necessario aggiungere la chiamata popBackStack() al metodo onBackPressed() dell'attività.

Es:

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

wow, grazie. Stavo operando sotto l'illusione che 'onBackPressed()' fornisce automaticamente questa funzionalità e deve essere solo sovrascritta quando si desiderano azioni speciali. – scottyseus

+1

@ScottScooterWeidenkopf: Popping a 'Fragment' È un'azione speciale. Il pulsante BACK era molto tempo prima che 'Fragments' e cambiandogli il comportamento predefinito nel codice base di Android non sarebbe stata una buona idea per ragioni di compatibilità con le versioni precedenti. Da qui il motivo per cui devi gestire le cose da solo. – Squonk

+1

Ok questo ha senso. Sono un newb quindi trascuro facilmente questi dettagli. Grazie per l'aiuto. – scottyseus

0

@ risposta di Bobbake4 è impressionante, ma c'è un piccolo problema. Diciamo che ho tre frammenti A, B e C. A è il frammento principale (il frammento che mostra quando lancio la mia app), B e C sono frammenti che posso navigare dal cassetto di navigazione o da A. Ora , quando uso il pulsante Indietro da B o C, torno al frammento precedente (A), ma il titolo del frammento precedente (frammento B o C) ora compare nel titolo ActionBar di Fragment A. Devo premere nuovamente il pulsante Indietro per completare "veramente" la navigazione posteriore (per visualizzare la vista e correggere il titolo per il frammento e tornare a)

Ecco come ho risolto questo problema. Dichiarare queste variabili.

public static boolean IS_FRAG_A_SHOWN = false; 
public static boolean IS_FRAG_B_SHOWN = false; 
public static boolean IS_FRAG_C_SHOWN = false; 

Nel MainActivity della mia app in cui sto trattando metodi cassetto di navigazione, Ho un metodo displayView(position) che gestisce la commutazione dei miei frammenti.

private void displayView(int position) { 
    IS_FRAG_A_SHOWN = false; 
    IS_FRAG_B_SHOWN = false; 
    IS_FRAG_C_SHOWN = false; 
    // update the main content by replacing fragments 
    Fragment fragment = null; 
    switch (position) { 
     case 0: 
      fragment = new FragmentA(); 
      IS_FRAG_A_SHOWN = true; 
      break; 
     case 1: 
      fragment = new FragmentB(); 
      IS_FRAG_B_SHOWN = true; 
      break; 
     case 2: 
      fragment = new FragmentC(); 
      IS_FRAG_C_SHOWN = true; 
      break; 

     default: 
      break; 
    } 

infine, nel mio metodo onBackPressed, faccio questo:

public void onBackPressed() { 
    if(fragmentManager.getBackStackEntryCount() != 0) { 
     fragmentManager.popBackStack(); 
     if (IS_FRAG_A_SHOWN) { //If we are in fragment A when we press the back button, finish is called to exit 
      finish(); 
     } else { 
      displayView(0); //else, switch to fragment A 
     } 

    } else { 
     super.onBackPressed(); 
    } 
} 
Problemi correlati