Android Fragmente und Animation

265

Wie sollten Sie die Art der Folie implementieren, die beispielsweise der Honeycomb Gmail-Client verwendet?

Kann TransactionManagerdies automatisch durch Hinzufügen und Entfernen der Fragmente handhaben. Es ist schwierig, dies zu testen, da der Emulator eine Diashow ist :)

alexanderblom
quelle

Antworten:

388

Um den Übergang zwischen Fragmenten zu animieren oder um das Ein- oder Ausblenden eines Fragments zu animieren, verwenden Sie das Fragment Manager, um ein Fragment zu erstellen Fragment Transaction.

Innerhalb jeder Fragmenttransaktion können Sie In- und Out-Animationen angeben, die zum Ein- und Ausblenden verwendet werden (oder beides, wenn Ersetzen verwendet wird).

Der folgende Code zeigt, wie Sie ein Fragment ersetzen würden, indem Sie ein Fragment herausschieben und das andere an seine Stelle schieben.

FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);

DetailsFragment newFragment = DetailsFragment.newInstance();

ft.replace(R.id.details_fragment_container, newFragment, "detailFragment");

// Start the animated transition.
ft.commit();

Um dasselbe zu erreichen, indem Sie ein Fragment verstecken oder anzeigen, das Sie einfach aufrufen ft.showoder ft.hidedas Fragment übergeben, das Sie anzeigen bzw. ausblenden möchten.

Als Referenz würden die XML-Animationsdefinitionen das objectAnimatorTag verwenden. Ein Beispiel für slide_in_left könnte ungefähr so ​​aussehen:

<?xml version="1.0" encoding="utf-8"?>
<set>
  <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="x" 
    android:valueType="floatType"
    android:valueFrom="-1280"
    android:valueTo="0" 
    android:duration="500"/>
</set>
Reto Meier
quelle
57
Als ich dies versuchte, zeigte es RuntimeException: Unbekannter Animatorname: translate .
Labeeb Panampullan
3
Stellen Sie sicher, dass die in slide_in_left und right definierten Animationen mithilfe einer Reihe von objectAnimator-Definitionen anstelle der alten Animationsdefinition erstellt werden.
Reto Meier
7
Das hat sehr geholfen. Ich war auf dem richtigen Weg, kam aber nicht ganz dorthin. Für die anderen Leser könnte auch android: interpolator als Attribut verwendet werden, wobei Ihr Favorit angegeben wird (z. B. "@android: interpolator / linear"). Der Standardwert ist "@android: Interpolator / Accelerate_Decelerate".
Dave MacLean
6
Ich ziele auf API Level 7 mit den Kompatibilitäts-APIs ab. Gibt es eine Möglichkeit für mich, Fragmente zu animieren?
Jarrod Smith
5
@JarrodSmith Sie können versuchen, eine Kompatibilitätsbibliothek wie NineOldAndroids zu verwenden, um die Honeycomb-API auf Eclair zu bringen.
Herr S
249

Wenn Sie die Support-Bibliothek nicht verwenden müssen, sehen Sie sich die Antwort von Roman an .

Wenn Sie jedoch die Support-Bibliothek verwenden möchten, müssen Sie das alte Animationsframework wie unten beschrieben verwenden.

Nachdem ich die Antworten von Reto und Blindstuff konsultiert habe, habe ich den folgenden Code zum Laufen gebracht .

Die Fragmente scheinen von rechts nach links und nach links zu rutschen, wenn der Rücken gedrückt wird.

FragmentManager fragmentManager = getSupportFragmentManager();

FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.pop_enter, R.anim.pop_exit);

CustomFragment newCustomFragment = CustomFragment.newInstance();
transaction.replace(R.id.fragment_container, newCustomFragment );
transaction.addToBackStack(null);
transaction.commit();

Die Reihenfolge ist wichtig. Dies bedeutet, dass Sie setCustomAnimations()vorher anrufen müssen, replace()sonst wird die Animation nicht wirksam!

Als nächstes müssen diese Dateien im Ordner res / anim abgelegt werden .

enter.xml :

<?xml version="1.0" encoding="utf-8"?>
<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="100%"
               android:toXDelta="0"
               android:interpolator="@android:anim/decelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

exit.xml :

<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="0"
               android:toXDelta="-100%"
               android:interpolator="@android:anim/accelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

pop_enter.xml :

<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="-100%"
               android:toXDelta="0"
               android:interpolator="@android:anim/decelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

pop_exit.xml :

<?xml version="1.0" encoding="utf-8"?>
<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="0"
               android:toXDelta="100%"
               android:interpolator="@android:anim/accelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

Die Dauer der Animationen kann auf einen der Standardwerte wie @android:integer/config_shortAnimTimeoder eine andere Zahl geändert werden .

Beachten Sie, dass die Zurückaktion nicht animiert wird, wenn zwischen dem Ersetzen von Fragmenten eine Konfigurationsänderung auftritt (z. B. Drehung). Dies ist ein dokumentierter Fehler , der in Version 20 der Support-Bibliothek noch vorhanden ist.

Dmanargien
quelle
47
Das hat mich nur gerettet. Beachten Sie, dass es wichtig ist , auf die Bestellung zu achten, die ich natürlich beim ersten Mal verpasst habe. Dies bedeutet, dass Sie setCustomAnimations () aufrufen müssen, bevor Sie replace ().
Stephen Kidson
3
Ich habe versucht, auf meinen Fragmenten zu implementieren. Ich habe alles wie erwähnt geschrieben, aber logcat sagt: Unbekannter Animatorname übersetzen Wie kann ich dieses Problem beheben? Übrigens rufe ich mein Fragment in der Navigationsschublade (Schiebemenü) an
Zafer Celaloglu
Funktioniert hervorragend, aber es stellt sich heraus, dass beim Erstellen mit Build-Tools 21.1 der Fehler "Ungültiger Dateiname: darf nur Kleinbuchstaben und Ziffern ([a-z0-9_.]) Enthalten" "generiert wird. Ich schlage vor, die Dateinamen in der Antwort auf pop_enter.xml und pop_exit.xml zu bearbeiten.
Smichak
Tolle Lösung und es funktioniert super, wenn ich den Zurück-Knopf drücke. Ich habe nur eine Frage: Wenn ich einen benutzerdefinierten backButton erstellen möchte, welchen Code sollte ich aufrufen, um das Verhalten über die Zurück-Schaltfläche zu replizieren?
Thomas Teilmann
1
Thomas, wenn Sie unterstützen möchten, sollten Sie dieses Formular implementieren: .setCustomAnimations (R.anim.pop_enter, R.anim.pop_exit, R.anim.enter, R.anim.exit)
Alex Zaraos
26

Ich würde dringend empfehlen, dies zu verwenden, anstatt die Animationsdatei zu erstellen, da dies eine viel bessere Lösung ist. Android Studio bietet bereits Standardeinstellungen, die animation Sie verwenden können, ohne eine neue XML-Datei zu erstellen. Die Namen der Animationen lauten android.R.anim.slide_in_left und android.R.anim.slide_out_right und können wie folgt verwendet werden:

fragmentTransaction.setCustomAnimations (android.R.anim.slide_in_left, android.R.anim.slide_out_right);

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();              
fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
fragmentManager.addOnBackStackChangedListener(this);
fragmentTransaction.replace(R.id.frame, firstFragment, "h");
fragmentTransaction.addToBackStack("h");
fragmentTransaction.commit();

Ausgabe:

Geben Sie hier die Bildbeschreibung ein

Gowthaman M.
quelle
1
android.R ... "Android Studio bietet Standardanimation", das ist nicht für Android Studio, es kann auch in Eclipse funktionieren, android.R ist androidspezifisch. Und übrigens haben Sie die Informationen nicht geteilt, welche APIs dies haben Sachen auf android.R sind auf verschiedenen apis unterschiedlich.
Steve Moretz
@stevemoretz thaxs bro Ich habe Ihrem Standpunkt zugestimmt. Ich werde meine Antwort korrigieren und aktualisieren ...
Gowthaman M
5

Meine modifizierte Unterstützungsbibliothek unterstützt die Verwendung von Ansichtsanimationen (dh <translate>, <rotate>) und Objektanimatoren (dh <objectAnimator>) für Fragmentübergänge. Es wird mit NineOldAndroids implementiert . Weitere Informationen finden Sie in meiner Dokumentation zu Github.

mark.kedzierski
quelle
2

Ich brauche die Ansichtsrichtung:

in -> von rechts wischen

out -> nach links wischen

Hier funktioniert für mich Code:

slide_in_right.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="50%p" android:toXDelta="0"
            android:duration="@android:integer/config_mediumAnimTime"/>
    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>

slide_out_left.xml

 <set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:fromXDelta="0" android:toXDelta="-50%p"
                android:duration="@android:integer/config_mediumAnimTime"/>
        <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
                android:duration="@android:integer/config_mediumAnimTime" />
    </set>

Transaktions-Code:

inline fun FragmentActivity.setContentFragment(
        containerViewId: Int,
        backStack: Boolean = false,
        isAnimate: Boolean = false,
        f: () -> Fragment

): Fragment? {
    val manager = supportFragmentManager
    return f().apply {
        manager.beginTransaction().let {
            if (isAnimate)
                it.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left)

            if (backStack) {
                it.replace(containerViewId, this, "Fr").addToBackStack("Fr").commit()
            } else {
                it.replace(containerViewId, this, "Fr").commit()
            }
        }
    }
}
Serg Burlaka
quelle
Android scheint die Übergänge mit diesen Animationen (insbesondere den übersetzten) zu flackern
Gabriel De Oliveira Rohden
@ GabrielDeOliveiraRohden wie für mich nicht in allen Klassen
Serg Burlaka
1

Ich löse das wie folgt

Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide);
fg.startAnimation(anim);
this.fg.setVisibility(View.VISIBLE); //fg is a View object indicate fragment
Shakawat Hossain
quelle