2014-11-01 13 views
22

I derzeit für Android eine Anwendung am Bau (14 < = SDK < = 21) von einer ActionBarActivity und Fragments verwenden, wie ListFragment und MapFragment, die innerhalb eines einzelnen vertauscht FrameLayout Ansicht.Fragment addToBackStack() und popBackStackImmediate() nicht funktioniert

Die ActionBarActivity ersetzt automatisch das/commit-Fragment A. Wenn der Benutzer dann auf eine Schaltfläche klickt, ersetzt/hostet die hostende Aktivität ein neues, anderes Fragment B. Mein Ziel ist es, den Benutzer so schnell wie möglich wieder auf Fragment A zu setzen drückt den Zurück-Knopf.

Einige Code jetzt.

MainActivity

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

Auch wenn addToBackStack() genannt wird, wenn ich auf dem Fragment B, bin ich direkt geschlossen nicht in der Lage zurück zu Fragmente A. MainActivity zu gehen. Dennoch habe ich versucht, den Backstack ohne Glück zu verwalten. Ich kann sehen, dass das Fragment auf dem Stapel ist, aber wenn ich popBackStackImmediate() rufe, wird Fragment A ausgeblendet und die Fragmenttransaktion wird nicht ausgeführt. (Erste Gegendruck nichts passieren, geschlossen zweite Aktivität)

Ich lege auch die FragmentManager logcat:
http://pastebin.com/hFLHprL8

Antwort

64

Für diejenigen, die für die Lösung suchen noch:
durch onBackPressed() zwingende gelöst.

In der Hauptklasse Activity (die die Fragmente hostet) überschreiben Sie einfach onBackPressed().

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

Es gibt keine onBackPressed() Methode Fragment, und dieses Verfahren ist nur für die activity. Wenn wir also die Zurück-Taste drücken, wird das Standardverhalten von activity gezeigt, was

ist

werden Sie entweder zur vorherige Tätigkeit gehen (wenn vorhanden) oder die App beendet.

Jetzt müssen wir diese Methode außer Kraft zu setzen, die activity zu sagen, dass, wenn wir die Zurück-Taste drücken, wenn es irgendwelche Fragmente im Rücken Stapel sind, knallen sie aus (und das ist, wenn die addToBackStack() kommt ins Bild). Ansonsten folgen Sie dem Standardverhalten.

+2

Vielen Dank. Ich frage mich, warum Android-Dokumentation diese wichtige Sache nicht erwähnt, oder ich vermisse es einfach ... – Ryde

5

die Sie interessieren (Anmerkung ersetzen hinzufügen nicht für fragmenta und addToBackStack() für fragmentB)

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

und

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

Auf diese Weise ich auf dem Stack Fragment B hinzufügen, aber nicht A. Von 'FragmentTransaction' Dokumentation: ' addToBackStack(): Fügen Sie diese Transaktion auf der Rückseite Stapel. Das bedeutet, dass die Transaktion nach dem Festschreiben gespeichert wird und ihre Operation rückgängig gemacht wird, wenn sie später vom Stapel genommen wird. – Emanuele

4

Ich musste beginTransaction() und commit() von FragmentManager manuell aufrufen.

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

Wenn Sie mit addToBackStack kämpfen() & popBackStack() dann einfach

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

in Ihrer Tätigkeit in OnBackPressed() finden fargment von Tag verwenden, und dann tun Sie Ihre Sachen

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

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

Für weitere Informationen https://github.com/DattaHujare/NavigationDrawer Ich verwende nie addBackStack() für die Handhabung von Fragment.

0

der Grund, warum die popBackStack() und popBackStackImmediatly() aufgrund der Tatsache ist, dass Sie das fragment nicht hinzugefügt haben (das Sie pop) zum backStack hinzufügen möchten. Um dies zu tun, müssen Sie einen Aufruf von addToBackStack() aufrufen, um die Transaktion zum Hinzufügen/Ersetzen Ihres Fragments durchzuführen.

Verwandte Themen