Fade In Fade Out Animation Android en Java

148

Je veux avoir une animation de 2 secondes d'un ImageView qui passe 1000 ms à fondu puis 1000 ms à disparaître.

Voici ce que j'ai jusqu'à présent dans mon constructeur ImageView:

Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setDuration(1000);

Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setStartOffset(1000);
fadeOut.setDuration(1000);

AnimationSet animation = new AnimationSet(true);
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
this.setAnimation(animation);

Lorsque je lance cette animation, rien ne s'affiche. Cependant, lorsque je supprime l'une des animations alpha, le comportement fonctionne comme prévu.

Choses que j'ai déjà essayées:

  • Toutes les combinaisons imaginables setFillBefore, setFillAfteret setFillEnabled.
  • Ajouter un LinearInterpolatorau AnimationSet.
laboureur
la source
1
Oui, vous pouvez fondre les images! Ce tutoriel devrait faire l'affaire. sankarganesh-info-exchange.blogspot.com/2011/04/…
Adam Storm
Ce didacticiel décrit une méthode utilisant XML. Savez-vous comment réaliser la même chose en utilisant Java?
laboureur
Eh bien, je ne suis pas à côté de mon ordinateur de programmation, donc je ne peux pas tester ce code, mais vous pouvez définir des attributs xml en java. il s'agit du code d'origine: android: interpolator = "@ android: anim / accelerate_interpolator" android: fromAlpha = "0.0" android: toAlpha = "1.0" android: duration = "300" /> \ n donc vous pouvez probablement MyTween.setDurationg (300) MyTween.fr deAlpha (0.0) MyTween (1.0)
Adam Storm

Réponses:

258

J'ai compris mon propre problème. La solution a fini par reposer sur des interpolateurs.

Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator()); //add this
fadeIn.setDuration(1000);

Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator()); //and this
fadeOut.setStartOffset(1000);
fadeOut.setDuration(1000);

AnimationSet animation = new AnimationSet(false); //change to false
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
this.setAnimation(animation);


Si vous utilisez Kotlin

val fadeIn = AlphaAnimation(0f, 1f)
fadeIn.interpolator = DecelerateInterpolator() //add this
fadeIn.duration = 1000

val fadeOut = AlphaAnimation(1f, 0f)
fadeOut.interpolator = AccelerateInterpolator() //and this
fadeOut.startOffset = 1000
fadeOut.duration = 1000

val animation = AnimationSet(false) //change to false
animation.addAnimation(fadeIn)
animation.addAnimation(fadeOut)
this.setAnimation(animation)
laboureur
la source
1
Et si vous voulez faire 5 ou 6 fading in / out, avec de très petits délais comme 100 pour chacun, pourriez-vous utiliser quelque chose comme ça? J'ai essayé mais ce n'est pas vraiment fluide. Le but était de simuler par exemple une ampoule qui ne fonctionnerait pas correctement, et qui scintillait.
Chayy
essayez d'appeler this.setAnimation in a loop
Jonathan
Je pensais que je me fanais de la dernière img bg et de la fad dans l'actuelle, mais cette réponse m'inspire que je n'ai besoin que de fondre dans l'img bg actuelle et de faire disparaître l'img actuelle, car AlphaAnimation ne peut pas fondre / sortir deux imgs différentes .
macio.Jun
8
Je ne pense pas que vous ayez besoin de deux animations indépendantes ... Je pense que vous pourriez avoir une seule animation et définir le paramètre: fadeInOut.setRepeatMode (Animation.REVERSE);
RoundSparrow hilltx
Deuxièmement: si vous vouliez répéter, pas besoin d'appeler en boucle comme le disait @jonney. utilisez fadeInOut.setRepeatCount (6) - remplacez 6 par le nombre que vous souhaitez qu'il répète. Beaucoup moins de frais généraux pour laisser le code C ++ natif dans Android faire tout cela au lieu d'appeler dans une boucle Java.
RoundSparrow hilltx
137

Je sais que cela a déjà été répondu mais .....

<?xml version="1.0" encoding="utf-8"?> 
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="1.0" 
    android:toAlpha="0.0" 
    android:duration="1000"    
    android:repeatCount="infinite" 
    android:repeatMode="reverse"
    />

Un moyen rapide et facile de faire rapidement un fondu entrant et sortant avec une répétition automatique. Prendre plaisir

EDIT : Dans votre activité, ajoutez ceci:

yourView.startAnimation(AnimationUtils.loadAnimation(co‌​ntext, R.anim.yourAnimation));
Konrad Winkowski
la source
6
+1 Parce qu'avec cette réponse, je pourrais faire une secuence de fondu d'entrée, de fondu de sortie et de fondu d'entrée (juste en réglant repeatCount = "2"). Je ne pouvais pas concaténer les animations comme le propose la réponse acceptée.
ElYeante
1
Après avoir déclaré cette alpharessource, comment puis-je l'utiliser?. Merci
zozelfelfo
1
zozelfelfo c'est juste un xml d'animation, alors chargez-le dans le code, puis appelez startAnimation sur la vue que vous voulez qu'il affecte.
Konrad Winkowski
La méthode @KonradWinkowski startAnimation nécessite un objet Animation comme argument! que dois-je lui passer?
Ahmad Vatani
Pour ceux qui recherchent une réponse plus complète viewToAnimate.startAnimation(AnimationUtils.loadAnimation(context, R.anim.fade_in_out):, où il y a un fichier fade_in_out.xml dans le dossier anim sous res.
Chris Knight
32
viewToAnimate.animate().alpha(1).setDuration(1000).setInterpolator(new DecelerateInterpolator()).withEndAction(new Runnable() {
    @Override
    public void run() {
        viewToAnimate.animate().alpha(0).setDuration(1000).setInterpolator(new AccelerateInterpolator()).start();
    }
}).start();
Vitaly Zinchenko
la source
4
Elegante pour guimauve!
LETs le
26

Voici ma solution utilisant AnimatorSet qui semble être un peu plus fiable que AnimationSet.

// Custom animation on image
ImageView myView = (ImageView)splashDialog.findViewById(R.id.splashscreenImage);

ObjectAnimator fadeOut = ObjectAnimator.ofFloat(myView, "alpha",  1f, .3f);
fadeOut.setDuration(2000);
ObjectAnimator fadeIn = ObjectAnimator.ofFloat(myView, "alpha", .3f, 1f);
fadeIn.setDuration(2000);

final AnimatorSet mAnimationSet = new AnimatorSet();

mAnimationSet.play(fadeIn).after(fadeOut);

mAnimationSet.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        mAnimationSet.start();
    }
});
mAnimationSet.start();
TWilly
la source
J'ai dû utiliser un ObjectAnimator au lieu d'une animation pour obtenir une solution fonctionnelle car pour une raison quelconque, chaque fois que je démarrais une AlphaAnimation, elle fonctionnait deux fois et faisait un scintillement étrange.
Andrew Orobator
solution élégante
Vlad
Eh bien, il est trop tard mais je pense que cela pourrait être utile, merci de bien effacer l'animation avant de l'utiliser à nouveau sur la même vue.
Bhavesh Moradiya
21

Une autre alternative:

Pas besoin de définir 2 animations pour fadeIn et fadeOut . fadeOut est l'inverse de fadeIn .

Vous pouvez donc le faire avec Animation.REVERSE comme ceci:

AlphaAnimation alphaAnimation = new AlphaAnimation(0.0f, 1.0f);
alphaAnimation.setDuration(1000);
alphaAnimation.setRepeatCount(1);
alphaAnimation.setRepeatMode(Animation.REVERSE);
view.findViewById(R.id.imageview_logo).startAnimation(alphaAnimation);

puis onAnimationEnd :

alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
    @Override
        public void onAnimationStart(Animation animation) {
            //TODO: Run when animation start
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            //TODO: Run when animation end
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            //TODO: Run when animation repeat
        }
    });
MarsPersonnes
la source
12

Comme je crois en la puissance de XML (pour les mises en page), c'est l'équivalent de la réponse acceptée , mais uniquement en tant que ressource d'animation:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/accelerate_decelerate"
    android:fillAfter="true">
    <alpha
        android:fromAlpha="0"
        android:toAlpha="1"
        android:duration="1000" />
    <alpha
        android:fromAlpha="1"
        android:toAlpha="0"
        android:duration="1000"
        android:startOffset="1000"/>
</set>

Le fillAfterfait que le fondu reste après la fin de l'animation. Les interpolatorpoignées interpolation des animations, comme vous pouvez le deviner. Vous pouvez également utiliser d'autres types d'interpolateurs, tels que Linéaire ou Dépassement.

Assurez-vous de démarrer votre animation sur votre vue:

yourView.startAnimation(AnimationUtils.loadAnimation(co‌​ntext, R.anim.fade));
DarkCygnus
la source
@KGCybeX pas de problème, heureux de pouvoir aider :)
DarkCygnus
1
Très serviable et propre. Fonctionne parfaitement pour moi.
Fernando Barbosa
9

Voici ce que j'utilisais pour fondre les vues d'entrée / sortie, j'espère que cela aide quelqu'un.

private void crossFadeAnimation(final View fadeInTarget, final View fadeOutTarget, long duration){
    AnimatorSet mAnimationSet = new AnimatorSet();
    ObjectAnimator fadeOut = ObjectAnimator.ofFloat(fadeOutTarget, View.ALPHA,  1f, 0f);
    fadeOut.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            fadeOutTarget.setVisibility(View.GONE);
        }

        @Override
        public void onAnimationCancel(Animator animation) {
        }

        @Override
        public void onAnimationRepeat(Animator animation) {
        }
    });
    fadeOut.setInterpolator(new LinearInterpolator());

    ObjectAnimator fadeIn = ObjectAnimator.ofFloat(fadeInTarget, View.ALPHA, 0f, 1f);
    fadeIn.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
            fadeInTarget.setVisibility(View.VISIBLE);
        }

        @Override
        public void onAnimationEnd(Animator animation) {}

        @Override
        public void onAnimationCancel(Animator animation) {}

        @Override
        public void onAnimationRepeat(Animator animation) {}
    });
    fadeIn.setInterpolator(new LinearInterpolator());
    mAnimationSet.setDuration(duration);
    mAnimationSet.playTogether(fadeOut, fadeIn);
    mAnimationSet.start();
}
Cristhian Escobar
la source
D'une manière ou d'une autre, c'est la seule réponse qui inclut le réglage de la visibilité, agréable
Luc
8

Les AnimationSets ne semblent pas du tout fonctionner comme prévu. À la fin, j'ai abandonné et utilisé le postDelayed () de la classe Handler pour séquencer les animations.

Richard
la source
8

Si vous utilisez Animator pour créer une animation, vous pouvez

anim (répertoire) -> fade_out.xml

<?xml version="1.0" encoding="UTF-8"?>
<objectAnimator
    android:propertyName="alpha"
    android:valueFrom="0"
    android:valueTo="1"
    xmlns:android="http://schemas.android.com/apk/res/android"/>

En java

Animator animator = AnimatorInflater.loadAnimator(context, R.animator.fade_out);
animator.setTarget(the_view_you_want_to_animation);
animator.setDuration(1000);
animator.start();

Une autre façon de faire disparaître l'animation avec uniquement du code Java est

ObjectAnimator fadeOut = ObjectAnimator.ofFloat(the_view_you_want_to_animation, "alpha",  1f, 0);
fadeOut.setDuration(2000);
fadeOut.start();
Phan Van Linh
la source
dans le répertoire anim * not animator
kosas
4

Vous pouvez également utiliser animationListener, quelque chose comme ceci:

fadeIn.setAnimationListener(new AnimationListener() {
    @Override
    public void onAnimationEnd(Animation animation) {
        this.startAnimation(fadeout);
    }
});
Omid Aminiva
la source
0

J'aime vraiment la solution Vitaly Zinchenkos car elle était courte.

Voici une version encore plus brève de kotlin pour un simple fondu

viewToAnimate?.alpha = 1f
viewToAnimate?.animate()
             ?.alpha(0f)
             ?.setDuration(1000)
             ?.setInterpolator(DecelerateInterpolator())
             ?.start()
Marc
la source