Fragmenttransaktionsanimation: ein- und ausschieben


104

Ich habe einige Tutorials auf animierte Transaktionen zwischen Fragmenten überprüft. Ich habe diese Methode für die Animation verwendet und sie funktioniert:

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

Aber ich möchte diese Animation umkehren: Das alte Fragment wird nach links und das neue Fragment nach rechts verschoben, aber kein Wert der R.animDatei scheint für meinen Bereich nützlich zu sein.

Wie kann ich es tun?


Meiner Meinung nach könnten Sie es override key_code==back_key_pressin Ihrem zweiten Fragment versuchen .
Nitin Misra

Vielleicht erkläre ich mich nicht gut. Ich möchte, dass beim Fragmentwechsel das alte Fragment auf der linken Seite verschoben wird und das neue Fragment von rechts eintritt. Mit diesem Code ist das Verhalten umgekehrt
Giozh

Antworten:


276

UPDATE Für Android v19 + siehe diesen Link über @Sandra

Sie können Ihre eigenen Animationen erstellen. Platzieren Sie Animations-XML-Dateien inres > anim

enter_from_left.xml

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

enter_from_right.xml

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

exit_to_left.xml

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

exit_to_right.xml

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

Sie können die Dauer auf kurze Animationszeit ändern

android:duration="@android:integer/config_shortAnimTime"

oder lange Animationszeit

android:duration="@android:integer/config_longAnimTime" 

VERWENDUNG (Beachten Sie, dass die Reihenfolge, in der Sie Methoden für die Transaktion aufrufen, von Bedeutung ist. Fügen Sie die Animation hinzu, bevor Sie .replace, .commit aufrufen.)

FragmentTransaction transaction = supportFragmentManager.beginTransaction();
transaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right);
transaction.replace(R.id.content_frame, fragment);
transaction.addToBackStack(null);
transaction.commit();

29
Verwenden Sie einfach diese XML-Animationen, wenn Sie Fragmente ersetzen, dh: fragmentTransaction.setCustomAnimations (R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right); fragmentTransaction.replace (R.id.content_frame, fragDettRisorsa); fragmentTransaction.addToBackStack (null); fragmentTransaction.commit ();
Moondroid

11
sein Sprichwort unbekannter Animatorname: übersetzen
Hirak Chhatbar

9
Es funktioniert nicht ... verursacht "java.lang.RuntimeException: Unbekannter Animatorname: translate". Diese Lösung hat bei mir funktioniert. trickyandroid.com/fragments-translate-animation
Ataru

27
Die Dauer 700ist meiner Meinung nach für solche Animationen etwas hoch. Das Android-Framework verfügt über 3 Voreinstellungen für das Timing : android:duration="@android:integer/config_longAnimTime", android:duration="@android:integer/config_mediumAnimTime"und android:duration="@android:integer/config_shortAnimTime", was 500, 400 und 200 entspricht. Ich denke, das Gerät ist Millisekunden, aber ich bin mir nicht sicher.
Krøllebølle

6
funktioniert nur bei Verwendung von Support-Fragmenten (android.support.v4.app.Fragment)
Aviv Ben Shabat

37

Es gibt drei Möglichkeiten zur Transaktionsanimation in Fragmenten.

Übergänge

Verwenden Sie also einen der integrierten Übergänge und die Methode setTranstion ():

getSupportFragmentManager()
        .beginTransaction()
        .setTransition( FragmentTransaction.TRANSIT_FRAGMENT_OPEN )
        .show( m_topFragment )
        .commit()

Benutzerdefinierte Animationen

Sie können die Animation auch mithilfe der setCustomAnimations () -Methode anpassen:

getSupportFragmentManager()
        .beginTransaction()
        .setCustomAnimations( R.anim.slide_up, 0, 0, R.anim.slide_down)
        .show( m_topFragment )
        .commit()

slide_up.xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:propertyName="translationY"
        android:valueType="floatType"
        android:valueFrom="1280"
        android:valueTo="0"
        android:duration="@android:integer/config_mediumAnimTime"/>

slide_down.xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:propertyName="translationY"
        android:valueType="floatType"
        android:valueFrom="0"
        android:valueTo="1280"
        android:duration="@android:integer/config_mediumAnimTime"/>

Mehrere Animationen

Schließlich ist es auch möglich, mehrere Fragmentanimationen in einer einzigen Transaktion zu starten. Dies ermöglicht einen ziemlich coolen Effekt, bei dem ein Fragment gleichzeitig nach oben und das andere nach unten rutscht:

getSupportFragmentManager()
        .beginTransaction()
        .setCustomAnimations( R.anim.abc_slide_in_top, R.anim.abc_slide_out_top ) // Top Fragment Animation
        .show( m_topFragment )
        .setCustomAnimations( R.anim.abc_slide_in_bottom, R.anim.abc_slide_out_bottom ) // Bottom Fragment Animation
        .show( m_bottomFragment )
        .commit()

Für weitere Informationen können Sie die URL besuchen

Hinweis: - Sie können die Animation gemäß Ihren Anforderungen überprüfen, da oben möglicherweise ein Problem vorliegt.


1
Sie verwenden einen absolut fest codierten Wert. Das vorherige Fragment wird für Anzeigen mit höherer Auflösung in der Mitte des Bildschirms ausgeblendet.
TheLibrarian

@ TheLibrarianCz dies ist nur ein Beispiel
Duggu

1
Es ist und es ist nicht.
TheLibrarian

Es hängt davon ab, dass jemand den Löffel aus dem obigen Beispiel füttern oder lernen möchte, was er mit dem Beispiel erreichen kann.
Duggu

Was ist in m_topFragment Variable
Prince

6

Ich habe das gleiche Problem, ich habe eine einfache Lösung verwendet

1) Erstellen Sie die Datei sliding_out_right.xml im Animationsordner

  <?xml version="1.0" encoding="utf-8"?>
    <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>

2) Erstellen Sie die Datei sliding_in_left.xml im Animationsordner

<?xml version="1.0" encoding="utf-8"?>
<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>

3) Verwenden Sie einfach die Fragmenttransaktion setCustomeAnimations () mit zwei benutzerdefinierten XML- und zwei Standard-XML-Dateien für die Animation wie folgt: -

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

5

slide_in_down.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@android:integer/config_longAnimTime"
        android:fromYDelta="0%p"
        android:toYDelta="100%p" />
</set>

slide_in_up.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@android:integer/config_longAnimTime"
        android:fromYDelta="100%p"
        android:toYDelta="0%p" />
</set>

slide_out_down.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@android:integer/config_longAnimTime"
        android:fromYDelta="-100%"
        android:toYDelta="0"
        />
</set>

slide_out_up.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@android:integer/config_longAnimTime"
        android:fromYDelta="0%p"
        android:toYDelta="-100%p"
        />
</set>

Richtung = nach unten

            activity.getSupportFragmentManager()
                    .beginTransaction()
                    .setCustomAnimations(R.anim.slide_out_down, R.anim.slide_in_down)
                    .replace(R.id.container, new CardFrontFragment())
                    .commit();

Richtung = nach oben

           activity.getSupportFragmentManager()
                    .beginTransaction()
                    .setCustomAnimations(R.anim.slide_in_up, R.anim.slide_out_up)
                    .replace(R.id.container, new CardFrontFragment())
                    .commit();

2

Dies ist eine andere Lösung, die ich benutze:

public class CustomAnimator {
    private static final String TAG = "com.example.CustomAnimator";

    private static Stack<AnimationEntry> animation_stack    = new Stack<>();

    public static final int                 DIRECTION_LEFT  = 1;
    public static final int                 DIRECTION_RIGHT = -1;
    public static final int                 DIRECTION_UP    = 2;
    public static final int                 DIRECTION_DOWN  = -2;

    static class AnimationEntry {
        View in;
        View    out;
        int     direction;
        long    duration;
    }

    public static boolean hasHistory() {
        return !animation_stack.empty();
    }

    public static void reversePrevious() {
        if (!animation_stack.empty()) {
            AnimationEntry entry = animation_stack.pop();
            slide(entry.out, entry.in, -entry.direction, entry.duration, false);
        }
    }

    public static void clearHistory() {
        animation_stack.clear();
    }

    public static void slide(final View in, View out, final int direction, long duration) {
        slide(in, out, direction, duration, true);
    }

    private static void slide(final View in, final View out, final int direction, final long duration, final boolean save) {

        ViewGroup in_parent = (ViewGroup) in.getParent();
        ViewGroup out_parent = (ViewGroup) out.getParent();

        if (!in_parent.equals(out_parent)) {
            return;
        }

        int parent_width = in_parent.getWidth();
        int parent_height = in_parent.getHeight();

        ObjectAnimator slide_out;
        ObjectAnimator slide_in;

        switch (direction) {
            case DIRECTION_LEFT:
            default:
                slide_in = ObjectAnimator.ofFloat(in, "translationX", parent_width, 0);
                slide_out = ObjectAnimator.ofFloat(out, "translationX", 0, -out.getWidth());
                break;
            case DIRECTION_RIGHT:
                slide_in = ObjectAnimator.ofFloat(in, "translationX", -out.getWidth(), 0);
                slide_out = ObjectAnimator.ofFloat(out, "translationX", 0, parent_width);
                break;
            case DIRECTION_UP:
                slide_in = ObjectAnimator.ofFloat(in, "translationY", parent_height, 0);
                slide_out = ObjectAnimator.ofFloat(out, "translationY", 0, -out.getHeight());
                break;
            case DIRECTION_DOWN:
                slide_in = ObjectAnimator.ofFloat(in, "translationY", -out.getHeight(), 0);
                slide_out = ObjectAnimator.ofFloat(out, "translationY", 0, parent_height);
                break;
        }

        AnimatorSet animations = new AnimatorSet();
        animations.setDuration(duration);
        animations.playTogether(slide_in, slide_out);
        animations.addListener(new Animator.AnimatorListener() {

            @Override
            public void onAnimationCancel(Animator arg0) {
            }

            @Override
            public void onAnimationEnd(Animator arg0) {
                out.setVisibility(View.INVISIBLE);
                if (save) {
                    AnimationEntry ae = new AnimationEntry();
                    ae.in = in;
                    ae.out = out;
                    ae.direction = direction;
                    ae.duration = duration;
                    animation_stack.push(ae);
                }
            }

            @Override
            public void onAnimationRepeat(Animator arg0) {
            }

            @Override
            public void onAnimationStart(Animator arg0) {
                in.setVisibility(View.VISIBLE);
            }
        });
        animations.start();
    }
}

Die Verwendung von Klasse. Angenommen, Sie haben zwei Fragmente (Listen- und Detailfragmente), wie unten gezeigt

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ui_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

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

    <FrameLayout
        android:id="@+id/details_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />
</FrameLayout>

Verwendung

View details_container = findViewById(R.id.details_container);
View list_container = findViewById(R.id.list_container);
// You can select the direction left/right/up/down and the duration
CustomAnimator.slide(list_container, details_container,CustomAnimator.DIRECTION_LEFT, 400);

Sie können die Funktion verwenden CustomAnimator.reversePrevious();, um die vorherige Ansicht abzurufen, wenn der Benutzer zurückgedrückt hat.


1
Bist du sicher, dass du Android's Fragmente verwendest? =) scheint ein benutzerdefiniertes Fragment-Management-View-basiertes System zu verwenden)
geküsst
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.