In Fragment auf Zurück-Taste gedrückt Aktivität ist leer

73

Ich habe eine Aktivität und viele Fragmente in derselben aufgeblasen FrameLayout

<FrameLayout
    android:id="@+id/content_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Beispiel: mainActivity> Beliebiges Fragment (Zurück-Taste drücken)> Aktivität ist leer.

In onCreate:

layout = (FrameLayout)findViewById(R.id.content_frame);
layout.setVisibility(View.GONE);

Wenn ich ein Fragment starte:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, profileFragment);
ft.addToBackStack(null);
ft.commit();
layout.setVisibility(View.VISIBLE);

Ich nehme an, ich muss die Sichtbarkeit des FrameLayout GONEerneut auf den Rücken drücken, aber wie mache ich das?


Ich habe versucht onBackPressedund eingestellt, layout.setVisibility(View.GONE);aber ich kann nicht durch Fragmente zurückgehen, da ich direkt zur Hauptseite gehe.

Filip Luchianenco
quelle
Wenn Sie von der Hauptaktivität gekommen sind, drücken Sie die Zurück-Taste. Was erwarten Sie?
Ivan Skoric
Ich erwarte, darauf zurückzukommen und es tatsächlich zu sehen. Da das FrameLayoutnoch sichtbar ist, möchte ich es unsichtbar machen, aber ich kann onBackPressed nicht überschreiben, da ich nicht wie folgt vorgehen kann: activity> fragment1> fragment2> onBackPressed geht direkt zur Aktivität und zeigt es an und überspringt fragment2
Filip Luchianenco
Aktualisieren Sie einfach Ihre OnCreateView () - Überschreibungsmethode für Ihr Fragment als stackoverflow.com/a/53813425/1298105
bitsugar

Antworten:

144

Wenn in der Aktivität mehr als ein Fragment verwendet wurde oder wenn Sie nur ein Fragment haben, sollte für das erste Fragment nicht addToBackStack definiert sein. Da dies eine Rückwärtsnavigation ermöglicht und vor diesem Fragment das leere Aktivitätslayout angezeigt wird.

 // fragmentTransaction.addToBackStack() // dont include this for your first fragment.

Für das andere Fragment muss dies jedoch definiert sein, da sonst die Rückseite nicht zu einem früheren Bildschirm (Fragment) navigiert, sondern die Anwendung möglicherweise heruntergefahren wird.

Sampath Kumar
quelle
Danke für die Antwort!! val sft = supportFragmentManager.beginTransaction() if (supportFragmentManager.fragments.isNotEmpty()) sft .addToBackStack(null) sft .commit()
Jose Pose S
So viele Stunden verschwendet, bis ich deine Antwort sah! danke Mann
Schlange
43
@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    }
    else {
        int fragments = getSupportFragmentManager().getBackStackEntryCount();
        if (fragments == 1) {
            finish();
        } else if (getFragmentManager().getBackStackEntryCount() > 1) {
            getFragmentManager().popBackStack();
        } else {
            super.onBackPressed();
        }
    }
}

Ein Fragment hinzufügen

 getSupportFragmentManager().beginTransaction()
                .replace(R.id.layout_main, dashboardFragment, getString(R.string.title_dashboard))
                .addToBackStack(getString(R.string.title_dashboard))
                .commit();
Gutes Leben
quelle
23

Entschuldigung für die späte Antwort.

Sie müssen ft.addToBackStack (null) nicht hinzufügen . beim Hinzufügen des ersten Fragments.

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, profileFragment);
// ft.addToBackStack(null); --remove this line.
ft.commit();
// ... rest of code
irscomp
quelle
1
Wir müssen müssen, wenn wir dieses Fragment haben, öffnet ein anderes Fragment. Wenn wir wieder auf das oberste klicken, wird es geschlossen.
MSaudi
Sehr nützlich, wenn wir eine Aktivität mit einem Fragment als Landing-Benutzeroberfläche erstellen. und dann können wir alle anderen Fragmente hinzufügen, wann immer dies mit addToBackStack (null) erforderlich ist.
Hardian
21

Wenn Sie anhand der Fragmente verfolgen möchten, sollten Sie die onBackPressedMethode wie folgt überschreiben

public void onBackPressed() { 
   if (getFragmentManager().getBackStackEntryCount() == 1) {
        finish();
   } else {
        super.onBackPressed();
   }
}
Edgar Sousa
quelle
15

Sie können überschreiben onBackPressedund überprüfen, ob sich etwas auf dem Backstack befindet.

@Override
public void onBackPressed() {
    int fragments = getFragmentManager().getBackStackEntryCount();
    if (fragments == 1) { 
        // make layout invisible since last fragment will be removed
    }
    super.onBackPressed();
}
JRomero
quelle
1
Ich habe den fragmentsWert überprüft , es ist immer 0, auch wenn es das zweite oder dritte Fragment ist.
Filip Luchianenco
Danke, aber ich bekomme immer noch 0. Ich habe es getFragmentManager().executePendingTransactions();vor jedem Fragment getan , auch ich habe die zweite Methode ausprobiert before fm.getBackStackEntryCount()und immer noch kein Glück.
Filip Luchianenco
5
Achtung, wenn Sie ein Fragment mit SupportedFragmentManager hinzufügen / ersetzen, sollten Sie auch getSupportFragmentManager () verwenden. GetBackStackEntryCount () und umgekehrt
David
3

Fügen Sie einfach nicht das erste Fragment zum Backstack hinzu

Hier ist der Kotlin-Code, der für mich funktioniert hat.

    val ft = supportFragmentManager.beginTransaction().replace(container, frag)
    if (!supportFragmentManager.fragments.isEmpty()) ft.addToBackStack(null)
    ft.commit()
Sileria
quelle
2

Bei einem kürzlich durchgeführten persönlichen Projekt habe ich dieses Problem gelöst, indem ich nicht aufgerufen habe, addToBackStackob der Stapel leer ist.

    // don't add the first fragment to the backstack
    // otherwise, pressing back on that fragment will result in a blank screen
    if (fragmentManager.getFragments() != null) {
        transaction.addToBackStack(tag);
    }

Hier ist meine vollständige Implementierung:

    String tag = String.valueOf(mCurrentSectionId);
    FragmentManager fragmentManager = mActivity.getSupportFragmentManager();
    Fragment fragment = fragmentManager.findFragmentByTag(tag);

    if (fragment != null) {
        // if the fragment exists then no need to create it, just pop back to it so
        // that repeatedly toggling between fragments doesn't create a giant stack
        fragmentManager.popBackStackImmediate(tag, 0);
    } else {
        // at this point, popping back to that fragment didn't happen
        // So create a new one and then show it
        fragment = createFragmentForSection(mCurrentSectionId);

        FragmentTransaction transaction = fragmentManager.beginTransaction()
                .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                .replace(R.id.main_content, fragment, tag);

        // don't add the first fragment to the backstack
        // otherwise, pressing back on that fragment will result in a blank screen
        if (fragmentManager.getFragments() != null) {
            transaction.addToBackStack(tag);
        }

        transaction.commit();
    }
gMännlich
quelle
1

Die Lösung von irscomp funktioniert, wenn Sie die Aktivität beenden möchten, wenn die Zurück-Taste auf dem ersten Fragment gedrückt wird. Wenn Sie jedoch alle Fragmente verfolgen und in umgekehrter Reihenfolge von einem zum anderen zurückkehren möchten, fügen Sie alle Fragmente hinzu, mit denen gestapelt werden soll:

ft.addToBackStack(null);

Fügen Sie dies am Ende von onCreate () hinzu, um zu vermeiden, dass beim letzten Zurückdrücken ein leerer Bildschirm angezeigt wird. Sie können getSupportFragmentManager () oder getFragmentManager () abhängig von Ihrer API verwenden:

FragmentManager fm = getSupportFragmentManager();
    fm.addOnBackStackChangedListener(new OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            if(getSupportFragmentManager().getBackStackEntryCount() == 0) finish();             
        }
});

Letzte Worte: Ich empfehle Ihnen nicht, diese Lösung zu verwenden, denn wenn Sie 10 Mal von Fragment1 zu Fragment 2 und umgekehrt wechseln und 10 Mal die Zurück-Taste drücken, geschieht dies in der Reihenfolge, in der die Benutzer dies nicht möchten.

Jemshit Iskenderov
quelle
1

Fast wie die Antwort von Goodlife , aber in gewisserXamarin.Android Weise:

Fragment laden ( ich habe dafür eine Hilfsmethode geschrieben, aber es ist nicht notwendig ):

public void LoadFragment(Activity activity, Fragment fragment, string fragmentTitle = "")
{
    var fragmentManager = activity.FragmentManager;
    var fragmentTransaction = fragmentManager.BeginTransaction();

    fragmentTransaction.Replace(Resource.Id.mainContainer, fragment);
    fragmentTransaction.AddToBackStack(fragmentTitle);

    fragmentTransaction.Commit();
}

Zurück-Taste ( inMainActivity ):

public override void OnBackPressed()
{
    if (isNavDrawerOpen()) drawerLayout.CloseDrawers();
    else
    {
        var backStackEntryCount = FragmentManager.BackStackEntryCount;

        if (backStackEntryCount == 1) Finish();
        else if (backStackEntryCount > 1) FragmentManager.PopBackStack();
        else base.OnBackPressed();
    }
}

Und isNavDrawerOpenMethode:

bool isNavDrawerOpen()
{
    return drawerLayout != null && drawerLayout.IsDrawerOpen(Android.Support.V4.View.GravityCompat.Start);
}
Mehdi Dehghani
quelle
1

Ich hatte das gleiche Problem beim Umgang mit dem Ui-Anmeldebildschirm von Firebase. Wenn die Zurück-Taste gedrückt wurde, blieb ein leerer Bildschirm übrig.

Um das Problem zu lösen, habe ich gerade finish()meine onStop()Methode für diese Aktivität aufgerufen . Lief wie am Schnürchen.

Jimmy Johnson
quelle
1

Ich konnte das Problem immer noch nicht beheben getBackStackEntryCount()und habe mein Problem gelöst, indem ich die Hauptseite ebenfalls zu einem Fragment gemacht habe. Am Ende habe ich also nur eine Aktivität mit einem FrameLayout; und alle anderen Fragmente, einschließlich der Hauptseite, die ich in dieses Layout aufblase. Dies löste mein Problem.

Filip Luchianenco
quelle
Das klingt ehrlich gesagt nach einem traditionellen Setup.
JRomero
Ich wusste nicht, dass dies traditionell ist, also habe ich das Fahrrad neu erfunden.
Filip Luchianenco
aber wie können wir Hauptseite als Fragment setzen
Mahesh
1. Aktivität erstellen 2. Fragment aufblasen und all deine Sachen dort machen. Schauen Sie sich diesen Link an. stackoverflow.com/questions/5159982/…
Filip Luchianenco