web-dev-qa-db-fra.com

Animation de transaction de fragment: glisser dans et sortir

J'ai vérifié des tutoriels pour animer une transaction entre des fragments. J'ai utilisé cette méthode pour l'animation et ça marche:

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

Mais je veux que l'animation soit inversée: l'ancien fragment glisse vers la gauche et le nouveau fragment vers la droite, mais aucune valeur de R.animfile ne semble être utile pour ma portée.

Comment puis-je le faire?

88
giozh

MISE À JOURPour Android v19 + voir ce lien via @Sandra

Vous pouvez créer vos propres animations. Placez les fichiers XML d'animation dans res > 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%" Android:toXDelta="0%"
      Android:fromYDelta="0%" Android:toYDelta="0%"
      Android:duration="700"/>
</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%" Android:toXDelta="0%"
     Android:fromYDelta="0%" Android:toYDelta="0%"
     Android:duration="700" />
</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%"
      Android:fromYDelta="0%" Android:toYDelta="0%"
      Android:duration="700"/>
</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%"
     Android:fromYDelta="0%" Android:toYDelta="0%"
     Android:duration="700" />
</set>

USAGE (notez que l'ordre dans lequel vous appelez des méthodes dans la transaction est important. Ajoutez l'animation avant d'appeler .replace, .commit):

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

Il y a trois façons d'animer une transaction en fragment.

Les transitions

Donc, vous devez utiliser l'une des transitions intégrées, utilisez la méthode setTranstion ():

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

Animations personnalisées

Vous pouvez également personnaliser l'animation à l'aide de la méthode setCustomAnimations ():

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"/>

Animations multiples

Enfin, il est également possible de lancer des animations de fragments multiples dans une seule transaction. Cela permet un effet assez cool où un fragment glisse vers le haut et l'autre glisse vers le bas en même temps:

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

Pour plus de détails, vous pouvez visiter l'URL

Remarque: - Vous pouvez vérifier l'animation en fonction de vos besoins car ce qui précède peut être un problème.

24
duggu

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>

direction = vers le bas

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

direction = haut

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

J'ai le même problème, j'ai utilisé une solution simple

1) créer slide_out_right.xml dans le dossier anim

  <?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) créer sliding_in_left.xml dans le dossier anim

<?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) simplement en utilisant fragment transaction setCustomeAnimations () avec deux XML personnalisés et deux XML par défaut pour l'animation comme suit: -

 fragmentTransaction.setCustomAnimations(R.anim.sliding_in_left, R.anim.sliding_out_right, Android.R.anim.slide_in_left, Android.R.anim.slide_out_right );
2
Mayuri Shinde

C'est une autre solution que j'utilise:

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

L'usage de la classe. Supposons que vous avez deux fragments (fragments de liste et détails) comme indiqué ci-dessous

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

tilisation

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

Vous pouvez utiliser la fonction CustomAnimator.reversePrevious();pour afficher la vue précédente lorsque l'utilisateur appuie en arrière.

2
COLD ICE