web-dev-qa-db-fra.com

Comment animer la suppression de fragments

Je veux animer la suppression de fragment.

J'ai essayé: 

getSupportFragmentManager().beginTransaction()
    .setCustomAnimations(R.anim.Push_down_in, R.anim.Push_up_out)
    .remove(myFragment)
    .commit();

mais le fragment disparaît tout simplement.

J'ai remarqué que l'animation sort uniquement avec 'replace', alors j'ai essayé de remplacer le fragment par un fragment vide comme ceci:

getSupportFragmentManager()
    .beginTransaction()
    .setCustomAnimations(R.anim.Push_down_in, R.anim.Push_up_out)
    .replace(viewId, new Fragment())
.commit();

Mais il ne fait que disparaître, disparaît.

Alors, comment puis-je animer la suppression de fragment?

30
hugoc

Je l'ai compris.

La vue sortante est animée sur la toile de la vue entrante. Ainsi, s'il n'y a pas de toile entrante, il n'y a pas de toile pour l'animation.

Pour afficher l'animation, je devais toujours utiliser remplacer et utiliser des fragments entrants de la même taille que ceux qui existaient déjà. Une fois l'animation terminée, je règle l'affichage des nouveaux fragments.

18
hugoc

J'ai vu cela quand j'avais des problèmes similaires et je pensais juste que Id laisserais tomber une note rapide.

Plutôt que de créer un fragment factice afin de remplacer celui qui existe, je pense que vous devriez animer la vue des fragments en cours. Lorsque l'animation est terminée, vous pouvez simplement supprimer le fragment.

Voici comment je l'ai fait:

final FragmentActivity a = getSherlockActivity();

if (a != null) {
    //Your animation
    Animation animation = AnimationUtils.loadAnimation(a, R.anim.bottom_out);
    animation.setDuration(getResources().getInteger(Android.R.integer.config_shortAnimTime));

    //You can use AnimationListener, MagicAnimationListener is simply a class extending it.
    animation.setAnimationListener(new MagicAnimationListener() {
        @Override
        public void onAnimationEnd(Animation animation) {
            //This is the key, when the animation is finished, remove the fragment.
            try {
                FragmentTransaction ft = a.getSupportFragmentManager().beginTransaction();
                ft.remove(RestTimerFragment.this);
                ft.commitAllowingStateLoss();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });

    //Start the animation.  
    getView().startAnimation(animation);
}
15
zoltish

Vous pouvez animer la suppression en définissant cette animation personnalisée sur fragmentTransaction.

        fragmentTransaction.setCustomAnimations(R.anim.right_in, R.anim.defff,R.anim.defff,R.anim.right_out);

Les troisième et quatrième paramètres servent à enlever le fragment

6
Antwan

Remplacer par un fragment vide, avant le point d'insertion du fragment suivant et retarder l'insertion du fragment suivant (de 200 ms) afin que l'animation de sortie du fragment vierge puisse jouer, a résolu mon problème.

C'est le code pour insérer un fragment vide avec une animation de sortie.

getSupportFragmentManager()
                        .beginTransaction()
                        .setCustomAnimations(R.anim.exit, R.anim.pop_exit)
                        .replace(R.id.fragmentLayout, new Fragment())
                        .commit();

Exit.xml 

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

</set>

pop_exit.xml

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

</set>
2
Ajit

raison comme @hugoc a dit

La vue sortante est animée sur la toile de la vue entrante. Ainsi, s'il n'y a pas de toile entrante, il n'y a pas de toile pour l'animation.

Pour afficher l'animation, je devais toujours utiliser remplacer et utiliser des fragments entrants de la même taille que ceux qui existaient déjà. Une fois l'animation terminée, je règle l'affichage des nouveaux fragments.

ci-dessous est le code actuel: 

FragmentManager manager = getSupportFragmentManager();
    FragmentTransaction transaction = manager.beginTransaction();
    transaction.setCustomAnimations(R.anim.slide_in_bottom, R.anim.slide_out_top);
    transaction.hide(removeFragment).add(R.id.fragment_container,addFragment).commit();
    transaction = manager.beginTransaction();
    transaction.remove(removeFragment).commit();
1
taotao

Je suis d'accord avec hugoc et voici un codepour le résoudre

public class MyActivity extends Activity {
    //Some thing
    public void Fragment2BackToFragment1(Fragment fragment1, Fragment fragment2) {
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction ft = manager.beginTransaction();
        animateExit(fragment2);
        ft.replace(R.id.main_content, fragment1, "fragment1");
        ft.commit();
    }
    private void animateExit(Fragment exitFragment) {
        if (exitFragment != null) {
            final View view = exitFragment.getView();
            if (view != null) {
                int anim = R.anim.fade_out;
                Animation animation =
                    AnimationUtils.loadAnimation(getActivity(), anim);
                animation.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        view.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                view.setVisibility(View.GONE);
                            }
                        }, 300);
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {


                    }
                });
                view.startAnimation(animation);
            }
        }
    }
}
1
hungnv39

Je me suis inspiré de la réponse de Zoltish, voici mon implémentation:

1.ajoutez cette méthode à l’intérieur du fragment, cela animera le fragment hors de l’écran à gauche:

public void animateOut()
{
    TranslateAnimation trans=new TranslateAnimation(0,-300*Utils.getDensity(getActivity()), 0,0);
    trans.setDuration(150);
    trans.setAnimationListener(new Animation.AnimationListener() {

        @Override
        public void onAnimationStart(Animation animation) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onAnimationEnd(Animation animation) {
            // TODO Auto-generated method stub
            ((BetsActivty)getActivity()).removeFrontFragmentAndSetControllToBetting();
        }
    });
    getView().startAnimation(trans);
}

La méthode à l'intérieur de onAnimationEnd () supprime le fragment comme ceci:

getSupportFragmentManager().beginTransaction().
        remove(getSupportFragmentManager().findFragmentById(R.id.fragment_container)).commit();

2.call l'animateOut du fragment de onBack () de l'activité.

À votre santé

À propos, mon getDensity () est:

public static int getDensity(Context context)
{
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    return (int)metrics.density;
}

avec lui, je calcule la valeur DP pour le périphérique en cours d’exécution.

1
Gal Rom

Donc le moyen le plus simple: 

Lorsque vous ouvrez un fragment (appelé de l'activité parent): 

    FragmentA fragment = new FragmentA();
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.setCustomAnimations(R.anim.slide_up, R.anim.slide_down);
    transaction.add(Android.R.id.content, fragment);
    transaction.addToBackStack(null);
    transaction.commit();

Spécifiez les transactions d'entrée et de sortie

transaction.setCustomAnimations (R.anim.slide_up, R.anim.slide_down);

Lors de la fermeture d'un fragment (appelé de l'intérieur du fragment)

getActivity().getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.slide_up, R.anim.slide_down).remove(this).commit();

Spécifiez les transactions d'entrée et de sortie

setCustomAnimations (R.anim.slide_up, R.anim.slide_down)

0
Siddharth Jaswal

setCustomAnimations (entrée, sortie, popEnter, popExit) support entrée et sortie de l'animation, définissez donc quatre animations et vous devez la conserver avant transaction.replace ()

Kotlin:

    val manager = supportFragmentManager
    val transaction = manager.beginTransaction()
    transaction.setCustomAnimations(Android.R.anim.slide_in_left, Android.R.anim.slide_out_right ,
            Android.R.anim.slide_in_left, Android.R.anim.slide_out_right)
    transaction.commit()
0

Une solution facile ci-dessous:

1-Call animate sur fragment.getView ().

2-Supprimer le fragment à l'intérieur de onAnimationEnd ().

final Fragment frag= getSupportFragmentManager().findFragmentById(R.id.fragmentContainer);
        frag.getView().animate().alpha(0f).scaleX(0f).scaleY(0f)

                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        getSupportFragmentManager()
                                .beginTransaction()
                                .remove(frag)
                                .commit();
                    }
                }).start();
0
Haytham Anmar

Ce qui entre:
c'est un nouveau fragment qui doit être montré

Quelle sortie:
c'est le fragment en cours qu'il faut cacher

Qu'est-ce que popEnter:
c'est le fragment précédent qui doit être montré

Quel popExit:
c'est le fragment en cours qu'il faut cacher

Pour utiliser ces animations, vous devez les cibler sur les commandes d’affichage ou de masquage des transactions. Les animations de sortie ne fonctionnent pas avec les procédures de suppression/remplacement.