web-dev-qa-db-de.com

Verschachtelte Fragmente verschwinden während der Übergangsanimation

Hier ist das Szenario: Die Aktivität enthält das Fragment A, das wiederum getChildFragmentManager() verwendet, um die Fragmente A1 und A2 in seiner onCreate hinzuzufügen:

getChildFragmentManager()
  .beginTransaction()
  .replace(R.id.fragmentOneHolder, new FragmentA1())
  .replace(R.id.fragmentTwoHolder, new FragmentA2())
  .commit()

So weit, so gut, läuft alles wie erwartet.

Wir führen dann die folgende Transaktion in der Aktivität aus: 

getSupportFragmentManager()
  .beginTransaction()
  .setCustomAnimations(anim1, anim2, anim1, anim2)
  .replace(R.id.fragmentHolder, new FragmentB())
  .addToBackStack(null)
  .commit()

Während des Übergangs werden die enter-Animationen für das Fragment B korrekt ausgeführt, die Fragmente A1 und A2 verschwinden jedoch vollständig. Wenn Sie die Transaktion mit der Zurück-Taste rückgängig machen, werden sie ordnungsgemäß initialisiert und während der popEnter-Animation normal angezeigt.

In meinen kurzen Tests wurde es merkwürdiger - wenn ich die Animationen für die untergeordneten Fragmente (siehe unten) setze, wird die exit-Animation intermittierend ausgeführt, wenn wir das Fragment B hinzufügen.

getChildFragmentManager()
  .beginTransaction()
  .setCustomAnimations(enter, exit)
  .replace(R.id.fragmentOneHolder, new FragmentA1())
  .replace(R.id.fragmentTwoHolder, new FragmentA2())
  .commit()

Der Effekt, den ich erzielen möchte, ist einfach: Ich möchte, dass die Animation exit (oder popExit?) Auf Fragment A (anim2) ausgeführt wird, wobei der gesamte Container einschließlich der verschachtelten Kinder animiert wird. 

Gibt es eine Möglichkeit, dies zu erreichen?

Edit: Hier finden Sie einen Testfall hier

Edit2: Vielen Dank an @StevenByle, dass Sie mich dazu gebracht haben, mich mit den statischen Animationen zu beschäftigen. Offensichtlich können Sie Animationen auf Pro-Op-Basis (nicht global für die gesamte Transaktion) festlegen. Dies bedeutet, dass die untergeordneten Elemente einen unbegrenzten statischen Animationssatz haben können, während das übergeordnete Element eine andere Animation haben kann und das Ganze in einer Transaktion ausgeführt werden kann . Siehe die folgende Diskussion und das aktualisierte Testfallprojekt .

93
Delyan

Um zu verhindern, dass der Benutzer die verschachtelten Fragmente verschwindet, wenn das übergeordnete Fragment in einer Transaktion entfernt/ersetzt wird, können Sie die noch vorhandenen Fragmente "simulieren", indem Sie ein Bild von ihnen so erstellen, wie sie auf dem Bildschirm erscheinen. Dieses Bild wird als Hintergrund für den Container für verschachtelte Fragmente verwendet. Selbst wenn die Ansichten des verschachtelten Fragments verschwinden, wird das Vorhandensein des Bildes jedoch simuliert. Ich sehe es auch nicht als ein Problem an, die Interaktivität mit den Ansichten des verschachtelten Fragments zu verlieren, weil ich nicht glaube, dass der Benutzer auf sie reagieren soll, wenn sie gerade entfernt werden (wahrscheinlich als Benutzeraktion als) Gut).

Ich habe ein kleines Beispiel mit dem Hintergrundbild (etwas Grundlegendes) gemacht.

34
Luksprog

Es scheint also viele verschiedene Problemumgehungen zu geben, aber basierend auf der Antwort von @ Jayd16 glaube ich, dass ich eine ziemlich solide Catch-All-Lösung gefunden habe, die immer noch benutzerdefinierte Übergangsanimationen für untergeordnete Fragmente zulässt und nicht zu tun ist ein Bitmap-Cache des Layouts.

Besitze eine BaseFragment-Klasse, die Fragment erweitert, und lass alle deine Fragmente diese Klasse erweitern (nicht nur untergeordnete Fragmente). 

Fügen Sie in dieser BaseFragment-Klasse Folgendes hinzu:

// Arbitrary value; set it to some reasonable default
private static final int DEFAULT_CHILD_ANIMATION_DURATION = 250;

@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
    final Fragment parent = getParentFragment();

    // Apply the workaround only if this is a child fragment, and the parent
    // is being removed.
    if (!enter && parent != null && parent.isRemoving()) {
        // This is a workaround for the bug where child fragments disappear when
        // the parent is removed (as all children are first removed from the parent)
        // See https://code.google.com/p/Android/issues/detail?id=55228
        Animation doNothingAnim = new AlphaAnimation(1, 1);
        doNothingAnim.setDuration(getNextAnimationDuration(parent, DEFAULT_CHILD_ANIMATION_DURATION));
        return doNothingAnim;
    } else {
        return super.onCreateAnimation(transit, enter, nextAnim);
    }
}

private static long getNextAnimationDuration(Fragment fragment, long defValue) {
    try {
        // Attempt to get the resource ID of the next animation that
        // will be applied to the given fragment.
        Field nextAnimField = Fragment.class.getDeclaredField("mNextAnim");
        nextAnimField.setAccessible(true);
        int nextAnimResource = nextAnimField.getInt(fragment);
        Animation nextAnim = AnimationUtils.loadAnimation(fragment.getActivity(), nextAnimResource);

        // ...and if it can be loaded, return that animation's duration
        return (nextAnim == null) ? defValue : nextAnim.getDuration();
    } catch (NoSuchFieldException|IllegalAccessException|Resources.NotFoundException ex) {
        Log.w(TAG, "Unable to load next animation from parent.", ex);
        return defValue;
    }
}

Es bedarf leider einer Reflexion; Da diese Problemumgehung jedoch für die Unterstützungsbibliothek gilt, besteht das Risiko, dass sich die zugrunde liegende Implementierung ändert, es sei denn, Sie aktualisieren Ihre Unterstützungsbibliothek. Wenn Sie die Unterstützungsbibliothek aus dem Quellcode erstellen, können Sie Fragment.Java einen Accessor für die nächste Animationsressourcen-ID hinzufügen und die Reflexion überflüssig machen.

Diese Lösung beseitigt die Notwendigkeit, die Animationsdauer des Elternteils zu "erraten" (damit die Animation "Nichts tun" die gleiche Dauer hat wie die Ausgangsanimation des Elternteils), und Sie können weiterhin benutzerdefinierte Animationen für untergeordnete Fragmente ausführen (z. B. wenn Sie tauschen Sie untergeordnete Fragmente mit verschiedenen Animationen aus.

66
kcoppock

Ich konnte eine ziemlich saubere Lösung finden. IMO ist der kleinste Hacker, und obwohl dies technisch gesehen die "draw a bitmap" -Lösung ist, wird sie zumindest durch das Fragment lib abstrahiert.

Stellen Sie sicher, dass Ihre untergeordneten Frags eine übergeordnete Klasse mit folgendem überschreiben:

private static final Animation dummyAnimation = new AlphaAnimation(1,1);
static{
    dummyAnimation.setDuration(500);
}

@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
    if(!enter && getParentFragment() != null){
        return dummyAnimation;
    }
    return super.onCreateAnimation(transit, enter, nextAnim);
}

Wenn wir für die untergeordneten Frags eine Beendigungsanimation haben, werden diese animiert, anstatt zu blinken. Wir können dies ausnutzen, indem wir eine Animation haben, die einfach die untergeordneten Fragmente für eine Dauer mit vollem Alpha zeichnet. Auf diese Weise bleiben sie im übergeordneten Fragment sichtbar, wenn sie animiert werden, wodurch das gewünschte Verhalten erhalten wird.

Das einzige Problem, das mir einfällt, ist, diese Dauer zu verfolgen. Ich könnte es auf eine große Zahl setzen, aber ich befürchte, dass es Performance-Probleme geben könnte, wenn die Animation noch irgendwo gezeichnet wird.

30
Jayd16

Ich poste meine Lösung aus Gründen der Klarheit .. Die Lösung ist ziemlich einfach. Wenn Sie versuchen, die Fragment-Transaktions-Animation des übergeordneten Objekts nachzuahmen, fügen Sie der untergeordneten Fragment-Transaktion einfach eine benutzerdefinierte Animation mit derselben Dauer hinzu. Oh, und stellen Sie sicher, dass Sie die benutzerdefinierte Animation vor dem Hinzufügen () festgelegt haben.

getChildFragmentManager().beginTransaction()
        .setCustomAnimations(R.anim.none, R.anim.none, R.anim.none, R.anim.none)
        .add(R.id.container, nestedFragment)
        .commit();

Die XML-Datei für R.anim.none (Meine Eltern betreten/beenden die Animationszeit beträgt 250 ms)

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <translate Android:fromXDelta="0" Android:toXDelta="0" Android:duration="250" />
</set>
14
Maurycy

Ich verstehe, dass dies möglicherweise nicht in der Lage ist, Ihr Problem vollständig zu lösen, aber möglicherweise wird es den Anforderungen anderer Personen entsprechen. Sie können enter/exit und popEnter/popExit Animationen zu Ihren Kindern Fragments hinzufügen, die die Fragments nicht bewegen/animieren. Solange die Animationen dieselbe Dauer/Versatz haben wie ihre Fragment-Animationen, scheinen sie sich mit der Animation des Elternteils zu bewegen/zu animieren.

7
Steven Byle

sie können dies im untergeordneten Fragment tun.

@Override
public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
    if (true) {//condition
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(getView(), "alpha", 1, 1);
        objectAnimator.setDuration(333);//time same with parent fragment's animation
        return objectAnimator;
    }
    return super.onCreateAnimator(transit, enter, nextAnim);
}
4
peng gao

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

EDIT: Ich habe diese Lösung nicht implementiert, da andere Probleme aufgetreten sind. Square hat kürzlich zwei Bibliotheken herausgebracht, die Fragmente ersetzen. Ich würde sagen, dass dies eine bessere Alternative sein könnte, als zu versuchen, Fragmente in etwas zu hacken, das Google nicht will.

http://corner.squareup.com/2014/01/mortar-and-flow.html

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Ich dachte mir, ich würde diese Lösung anbieten, um Menschen zu helfen, die dieses Problem in der Zukunft haben. Wenn Sie durch die Konversation des Originalplakats mit anderen Personen nachverfolgen und den von ihm geposteten Code betrachten, werden Sie feststellen, dass das Originalposter letztendlich zu der Schlussfolgerung kommt, dass bei den untergeordneten Fragmenten eine No-Op-Animation verwendet wird, während das übergeordnete Fragment animiert wird. Diese Lösung ist nicht ideal, da Sie dazu gezwungen werden, alle untergeordneten Fragmente zu verfolgen, was bei Verwendung eines ViewPagers mit FragmentPagerAdapter mühsam sein kann.

Da ich Child Fragments überall benutze, habe ich diese Lösung gefunden, die effizient und modular ist (so dass sie leicht entfernt werden kann), falls sie jemals repariert werden sollten und diese No-Op-Animation nicht mehr benötigt wird.

Es gibt viele Möglichkeiten, dies umzusetzen. Ich entschied mich für ein Singleton und nenne es ChildFragmentAnimationManager. Es wird im Grunde ein untergeordnetes Fragment für mich auf der Grundlage des übergeordneten Elements nachverfolgen und auf die Kinder eine No-Op-Animation anwenden, wenn Sie dazu aufgefordert werden.

public class ChildFragmentAnimationManager {

private static ChildFragmentAnimationManager instance = null;

private Map<Fragment, List<Fragment>> fragmentMap;

private ChildFragmentAnimationManager() {
    fragmentMap = new HashMap<Fragment, List<Fragment>>();
}

public static ChildFragmentAnimationManager instance() {
    if (instance == null) {
        instance = new ChildFragmentAnimationManager();
    }
    return instance;
}

public FragmentTransaction animate(FragmentTransaction ft, Fragment parent) {
    List<Fragment> children = getChildren(parent);

    ft.setCustomAnimations(R.anim.no_anim, R.anim.no_anim, R.anim.no_anim, R.anim.no_anim);
    for (Fragment child : children) {
        ft.remove(child);
    }

    return ft;
}

public void putChild(Fragment parent, Fragment child) {
    List<Fragment> children = getChildren(parent);
    children.add(child);
}

public void removeChild(Fragment parent, Fragment child) {
    List<Fragment> children = getChildren(parent);
    children.remove(child);
}

private List<Fragment> getChildren(Fragment parent) {
    List<Fragment> children;

    if ( fragmentMap.containsKey(parent) ) {
        children = fragmentMap.get(parent);
    } else {
        children = new ArrayList<Fragment>(3);
        fragmentMap.put(parent, children);
    }

    return children;
}

}

Als Nächstes benötigen Sie eine Klasse, die Fragment erweitert, das alle Ihre Fragmente erweitern (zumindest Ihre untergeordneten Fragmente). Ich hatte diese Klasse bereits und ich nenne sie BaseFragment. Wenn eine Fragmentansicht erstellt wird, fügen wir sie dem ChildFragmentAnimationManager hinzu und entfernen sie, wenn sie zerstört wird. Sie können dies onAttach/Detach oder andere passende Methoden in der Sequenz ausführen. Meine Logik bei der Auswahl von „Ansicht erstellen/zerstören“ war, dass es mir egal ist, wenn ein Fragment keine Ansicht hat, dass es nicht animiert wird, es zu animieren, damit es weiterhin angezeigt wird. Dieser Ansatz sollte auch besser mit ViewPagers funktionieren, die Fragmente verwenden, da Sie nicht jedes einzelne Fragment, das ein FragmentPagerAdapter enthält, im Auge behalten, sondern nur 3.

public abstract class BaseFragment extends Fragment {

@Override
public  View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    Fragment parent = getParentFragment();
    if (parent != null) {
        ChildFragmentAnimationManager.instance().putChild(parent, this);
    }

    return super.onCreateView(inflater, container, savedInstanceState);
}

@Override
public void onDestroyView() {
    Fragment parent = getParentFragment();
    if (parent != null) {
        ChildFragmentAnimationManager.instance().removeChild(parent, this);
    }

    super.onDestroyView();
}

}

Da nun alle Ihre Fragmente vom übergeordneten Fragment im Speicher abgelegt werden, können Sie sie wie folgt animieren, und Ihre untergeordneten Fragmente werden nicht verschwinden.

FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ChildFragmentAnimationManager.instance().animate(ft, ReaderFragment.this)
                    .setCustomAnimations(R.anim.up_in, R.anim.up_out, R.anim.down_in, R.anim.down_out)
                    .replace(R.id.container, f)
                    .addToBackStack(null)
                    .commit();

Genau so, wie Sie es haben, hier ist die no_anim.xml-Datei, die sich in Ihrem res/anim-Ordner befindet:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:Android="http://schemas.Android.com/apk/res/Android" Android:interpolator="@Android:anim/linear_interpolator">
    <translate Android:fromXDelta="0" Android:toXDelta="0"
        Android:duration="1000" />
</set>

Ich denke nicht, dass diese Lösung perfekt ist, aber es ist viel besser als für jede Instanz, bei der Sie ein untergeordnetes Fragment haben, und benutzerdefinierten Code in das übergeordnete Fragment implementieren, um jedes Kind zu überwachen. Ich war dort und es macht keinen Spaß.

2
spierce7

Ich hatte das gleiche Problem mit dem Kartenfragment. Während der Ausgangsanimation des enthaltenen Fragments verschwand es ständig. Um dieses Problem zu umgehen, fügen Sie eine Animation für das untergeordnete Kartenfragment hinzu, die während der Exit-Animation des übergeordneten Fragmentes sichtbar bleibt. Die Animation des untergeordneten Fragments behält während der Dauer seines Alphas 100% bei.

Animation: res/animator/keep_child_fragment.xml

<?xml version="1.0" encoding="utf-8"?>    
<set xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <objectAnimator
        Android:propertyName="alpha"
        Android:valueFrom="1.0"
        Android:valueTo="1.0"
        Android:duration="@integer/keep_child_fragment_animation_duration" />
</set>

Die Animation wird dann angewendet, wenn das Kartenfragment dem übergeordneten Fragment hinzugefügt wird.

Übergeordnetes Fragment

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.map_parent_fragment, container, false);

    MapFragment mapFragment =  MapFragment.newInstance();

    getChildFragmentManager().beginTransaction()
            .setCustomAnimations(R.animator.keep_child_fragment, 0, 0, 0)
            .add(R.id.map, mapFragment)
            .commit();

    return view;
}

Schließlich wird die Dauer der Animation des untergeordneten Fragments in einer Ressourcendatei festgelegt.

Werte/Ganzzahlen.xml

<resources>
  <integer name="keep_child_fragment_animation_duration">500</integer>
</resources>
1
Evgenii

Das Problem ist in androidx.fragment:fragment:1.2.0-alpha02 behoben. Weitere Informationen finden Sie unter https://issuetracker.google.com/issues/11667531 .

0

Eine einfache Möglichkeit, dieses Problem zu beheben, ist die Verwendung der Fragment-Klasse aus dieser Bibliothek anstelle der Standard-Bibliotheksfragmentklasse:

https://github.com/marksalpeter/contract-fragment

Als Nebenbemerkung enthält das Paket auch ein nützliches Delegatemuster mit dem Namen ContractFragment, das Sie möglicherweise beim Erstellen Ihrer Apps unter Verwendung der Parent-Child-Fragment-Beziehung als nützlich erachten.

0
Mark Salpeter

Um das Verschwinden von genähten Fragmenten zu animieren, können wir ChildFragmentManager einen Pop-Back-Stack erzwingen. Dadurch wird eine Übergangsanimation ausgelöst. Dazu müssen wir das OnBackButtonPressed-Ereignis nachholen oder auf Backstack-Änderungen achten.

Hier ist ein Beispiel mit Code. 

View.OnClickListener() {//this is from custom button but you can listen for back button pressed
            @Override
            public void onClick(View v) {
                getChildFragmentManager().popBackStack();
                //and here we can manage other fragment operations 
            }
        });

  Fragment fr = MyNeastedFragment.newInstance(product);

  getChildFragmentManager()
          .beginTransaction()
                .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE)
                .replace(R.neasted_fragment_container, fr)
                .addToBackStack("Neasted Fragment")
                .commit();
0
Mateusz Biedron

Ich bin vor kurzem in meiner Frage auf dieses Problem gestoßen: Verschachtelte Fragmente werden nicht richtig übertragen

Ich habe eine Lösung, die dieses Problem löst, ohne eine Bitmap zu speichern oder Reflexion oder andere unbefriedigende Methoden zu verwenden.

Ein Beispielprojekt kann hier angezeigt werden: https://github.com/zafrani/NestedFragmentTransitions

Ein GIF des Effekts kann hier eingesehen werden: https://imgur.com/94AvrW4

In meinem Beispiel gibt es 6 Kinderfragmente, die auf zwei Elternfragmente aufgeteilt sind. Ich kann die Übergänge für enter, exit, pop und Push ohne Probleme erreichen. Konfigurationsänderungen und Rückpressen werden ebenfalls erfolgreich behandelt.

Die Masse der Lösung befindet sich in meiner BaseFragment-Funktion (das von meinen untergeordneten und übergeordneten Fragmenten erweiterte Fragment) onCreateAnimator-Funktion, die wie folgt aussieht:

   override fun onCreateAnimator(transit: Int, enter: Boolean, nextAnim: Int): Animator {
    if (isConfigChange) {
        resetStates()
        return nothingAnim()
    }

    if (parentFragment is ParentFragment) {
        if ((parentFragment as BaseFragment).isPopping) {
            return nothingAnim()
        }
    }

    if (parentFragment != null && parentFragment.isRemoving) {
        return nothingAnim()
    }

    if (enter) {
        if (isPopping) {
            resetStates()
            return pushAnim()
        }
        if (isSuppressing) {
            resetStates()
            return nothingAnim()
        }
        return enterAnim()
    }

    if (isPopping) {
        resetStates()
        return popAnim()
    }

    if (isSuppressing) {
        resetStates()
        return nothingAnim()
    }

    return exitAnim()
}

Die Aktivität und das übergeordnete Fragment sind für die Festlegung der Zustände dieser Booleschen Objekte verantwortlich. Es ist einfacher zu sehen, wie und wo aus meinem Beispielprojekt.

Ich verwende keine Unterstützungsfragmente in meinem Beispiel, aber dieselbe Logik kann mit ihnen und ihrer onCreateAnimation-Funktion verwendet werden

0
zafrani

Mein Problem war das Entfernen von Elternfragmenten (ft.remove (fragment)), Kinderanimationen traten nicht auf.

Das Grundproblem besteht darin, dass untergeordnete Fragmente sofort VOR dem Elternfragment, das die Animation verlässt, ZERSTÖRT werden.

Benutzerdefinierte Animationen für untergeordnete Fragmente werden beim Entfernen des übergeordneten Fragments nicht ausgeführt

Wie andere sich entzogen haben, ist es der richtige Weg, die ELTERN (und nicht das Kind) vor der Entfernung der ELTERN zu verstecken.

            val ft = fragmentManager?.beginTransaction()
            ft?.setCustomAnimations(R.anim.enter_from_right,
                    R.anim.exit_to_right)
            if (parentFragment.isHidden()) {
                ft?.show(vehicleModule)
            } else {
                ft?.hide(vehicleModule)
            }
            ft?.commit()

Wenn Sie das übergeordnete Element tatsächlich entfernen möchten, sollten Sie wahrscheinlich einen Listener für Ihre benutzerdefinierte Animation einrichten, um zu erfahren, wann die Animation beendet ist, damit Sie das übergeordnete Fragment sicher finalisieren (entfernen) können. Wenn Sie dies nicht rechtzeitig tun, wird die Animation möglicherweise beendet. Die Animation erfolgt in einer eigenen asynchronen Warteschlange.

Übrigens benötigen Sie keine benutzerdefinierten Animationen für das untergeordnete Fragment, da diese die übergeordneten Animationen erben.

0
Ed Manners

Ich glaube, ich habe eine bessere Lösung für dieses Problem gefunden, als das aktuelle Fragment in einer Bitmap zu schnappen, wie Luksprog vorschlug.

Der Trick besteht darin, hide das Fragment wird entfernt oder getrennt, und erst nachdem die Animationen abgeschlossen sind, wird das Fragment in seiner eigenen Fragment-Transaktion entfernt oder getrennt.

Stellen Sie sich vor, wir haben FragmentA und FragmentB, beide mit Unterfragmenten. Nun, wenn Sie normalerweise tun würden:

getSupportFragmentManager()
  .beginTransaction()
  .setCustomAnimations(anim1, anim2, anim1, anim2)
  .add(R.id.fragmentHolder, new FragmentB())
  .remove(fragmentA)    <-------------------------------------------
  .addToBackStack(null)
  .commit()

Stattdessen tun Sie es

getSupportFragmentManager()
  .beginTransaction()
  .setCustomAnimations(anim1, anim2, anim1, anim2)
  .add(R.id.fragmentHolder, new FragmentB())
  .hide(fragmentA)    <---------------------------------------------
  .addToBackStack(null)
  .commit()

fragmentA.removeMe = true;

Nun zur Implementierung des Fragments:

public class BaseFragment extends Fragment {

    protected Boolean detachMe = false;
    protected Boolean removeMe = false;

    @Override
    public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
        if (nextAnim == 0) {
            if (!enter) {
                onExit();
            }

            return null;
        }

        Animation animation = AnimationUtils.loadAnimation(getActivity(), nextAnim);
        assert animation != null;

        if (!enter) {
            animation.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    onExit();
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                }
            });
        }

        return animation;
    }

    private void onExit() {
        if (!detachMe && !removeMe) {
            return;
        }

        FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
        if (detachMe) {
            fragmentTransaction.detach(this);
            detachMe = false;
        } else if (removeMe) {
            fragmentTransaction.remove(this);
            removeMe = false;
        }
        fragmentTransaction.commit();
    }
}
0
Danilo

Aus der obigen Antwort von @kcoppock:

wenn Sie über Aktivität-> Fragment-> Fragmente verfügen (mehrfaches Stapeln, hilft die folgende), eine geringfügige Bearbeitung der besten Antwort IMHO.

public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {

    final Fragment parent = getParentFragment();

    Fragment parentOfParent = null;

    if( parent!=null ) {
        parentOfParent = parent.getParentFragment();
    }

    if( !enter && parent != null && parentOfParent!=null && parentOfParent.isRemoving()){
        Animation doNothingAnim = new AlphaAnimation(1, 1);
        doNothingAnim.setDuration(getNextAnimationDuration(parent, DEFAULT_CHILD_ANIMATION_DURATION));
        return doNothingAnim;
    } else
    if (!enter && parent != null && parent.isRemoving()) {
        // This is a workaround for the bug where child fragments disappear when
        // the parent is removed (as all children are first removed from the parent)
        // See https://code.google.com/p/Android/issues/detail?id=55228
        Animation doNothingAnim = new AlphaAnimation(1, 1);
        doNothingAnim.setDuration(getNextAnimationDuration(parent, DEFAULT_CHILD_ANIMATION_DURATION));
        return doNothingAnim;
    } else {
        return super.onCreateAnimation(transit, enter, nextAnim);
    }
}
0
alekshandru