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.


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.


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

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

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

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

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

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

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.


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

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.


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.


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.