Android fade in et fade out avec ImageView

J'ai quelques problèmes avec un diaporama que je construis.

J'ai créé 2 animations en xml pour fade in et fade out:

Fadein.xml

    <?xml version="1.0" encoding="UTF-8"?>
       <set xmlns:android="http://schemas.android.com/apk/res/android">
         <alpha android:fromAlpha="0.0" android:toAlpha="1.0" 
          android:interpolator="@android:anim/accelerate_interpolator" 
          android:duration="2000"/>
     </set>

Fadeout.xml

    <?xml version="1.0" encoding="UTF-8"?>
       <set xmlns:android="http://schemas.android.com/apk/res/android">
         <alpha android:fromAlpha="1.0" android:toAlpha="0.0" 
          android:interpolator="@android:anim/accelerate_interpolator" 
          android:duration="2000"/>
     </set>

Ce que je cherche à faire, c'est de changer les images d'un ImageView en utilisant l'effet de fondu, de sorte que l'image actuellement affichée disparaîtra, et une autre disparaîtra. Considérant que j'ai déjà une image définie, je peux effacer cette Image sans problème, avec ce:

    Animation fadeInAnimation = AnimationUtils.loadAnimation(this, R.anim.your_fade_in_anim);
    imageView.startAnimation(fadeoutAnim);

Mais ensuite, je mets l'image suivante à afficher:

    imageView.setImageBitmap(secondImage);

, Il s'affiche dans la imageView, et quand je l'animation il cache l'image, la en fondu... Est - il possible de résoudre ce problème, je veux dire, quand je fais imageView.setimagebitmap (secondImage); commande, l'image ne s'affiche pas immédiatement, et seulement lorsque le fondu dans l'animation est exécuté?

79
demandé sur Eric Brandwein 2012-01-04 04:29:12

10 réponses

Pour l'implémenter comme vous l'avez commencé, vous devrez ajouter un AnimationListener afin de détecter le début et la fin d'une animation. Lorsque onAnimationEnd() pour le fondu est appelé, vous pouvez définir la visibilité de votre objet ImageView sur View.INVISIBLE, changez les images et commencez votre fondu dans l'animation-vous aurez besoin d'un autre AnimationListener ici aussi. Lorsque vous recevez onAnimationEnd () pour votre fondu dans l'animation, définissez ImageView sur View.Le VISIBLE et l' devrait vous donner l'effet que vous recherchez.

J'ai déjà implémenté un effet similaire, mais j'ai utilisé un ViewSwitcher avec 2 ImageViews plutôt qu'un seul ImageView. Vous pouvez définir les animations " in " et " out " pour ViewSwitcher avec votre fade in et fade out afin qu'il puisse gérer L'implémentation AnimationListener. Ensuite, tout ce que vous devez faire est d'alterner entre les 2 ImageViews.

Modifier: Pour être un peu plus utile, voici un rapide exemple d'utilisation de la ViewSwitcher. J'ai inclus la source à https://github.com/aldryd/imageswitcher.

Activity_main.xml

    <ViewSwitcher
        android:id="@+id/switcher"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:inAnimation="@anim/fade_in"
        android:outAnimation="@anim/fade_out" >

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scaleType="fitCenter"
            android:src="@drawable/sunset" />

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scaleType="fitCenter"
            android:src="@drawable/clouds" />
    </ViewSwitcher>

MainActivity.java

    // Let the ViewSwitcher do the animation listening for you
    ((ViewSwitcher) findViewById(R.id.switcher)).setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            ViewSwitcher switcher = (ViewSwitcher) v;

            if (switcher.getDisplayedChild() == 0) {
                switcher.showNext();
            } else {
                switcher.showPrevious();
            }
        }
    });
62
répondu Aldryd 2012-12-16 07:03:41

Je voulais atteindre le même objectif que vous, alors j'ai écrit la méthode suivante qui fait exactement cela si vous lui passez un ImageView et une liste de références à image drawables.

ImageView demoImage = (ImageView) findViewById(R.id.DemoImage);
int imagesToShow[] = { R.drawable.image1, R.drawable.image2,R.drawable.image3 };

animate(demoImage, imagesToShow, 0,false);  



  private void animate(final ImageView imageView, final int images[], final int imageIndex, final boolean forever) {

  //imageView <-- The View which displays the images
  //images[] <-- Holds R references to the images to display
  //imageIndex <-- index of the first image to show in images[] 
  //forever <-- If equals true then after the last image it starts all over again with the first image resulting in an infinite loop. You have been warned.

    int fadeInDuration = 500; // Configure time values here
    int timeBetween = 3000;
    int fadeOutDuration = 1000;

    imageView.setVisibility(View.INVISIBLE);    //Visible or invisible by default - this will apply when the animation ends
    imageView.setImageResource(images[imageIndex]);

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

    Animation fadeOut = new AlphaAnimation(1, 0);
    fadeOut.setInterpolator(new AccelerateInterpolator()); // and this
    fadeOut.setStartOffset(fadeInDuration + timeBetween);
    fadeOut.setDuration(fadeOutDuration);

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

    animation.setAnimationListener(new AnimationListener() {
        public void onAnimationEnd(Animation animation) {
            if (images.length - 1 > imageIndex) {
                animate(imageView, images, imageIndex + 1,forever); //Calls itself until it gets to the end of the array
            }
            else {
                if (forever){
                animate(imageView, images, 0,forever);  //Calls itself to start the animation all over again in a loop if forever = true
                }
            }
        }
        public void onAnimationRepeat(Animation animation) {
            // TODO Auto-generated method stub
        }
        public void onAnimationStart(Animation animation) {
            // TODO Auto-generated method stub
        }
    });
}
95
répondu Crocodile 2017-02-08 15:12:32

Avez-vous pensé à utiliser TransitionDrawable au lieu d'animations personnalisées? https://developer.android.com/reference/android/graphics/drawable/TransitionDrawable.html

Une façon de réaliser ce que vous cherchez est:

// create the transition layers
Drawable[] layers = new Drawable[2];
layers[0] = new BitmapDrawable(getResources(), firstBitmap);
layers[1] = new BitmapDrawable(getResources(), secondBitmap);

TransitionDrawable transitionDrawable = new TransitionDrawable(layers);
imageView.setImageDrawable(transitionDrawable);
transitionDrawable.startTransition(FADE_DURATION);
41
répondu munkay 2013-05-08 14:40:05

Basé sur la solution D'Aladin Q, voici une fonction d'aide que j'ai écrite, qui va changer l'image dans un imageview tout en exécutant un petit fondu / fondu dans l'animation:

public static void ImageViewAnimatedChange(Context c, final ImageView v, final Bitmap new_image) {
        final Animation anim_out = AnimationUtils.loadAnimation(c, android.R.anim.fade_out); 
        final Animation anim_in  = AnimationUtils.loadAnimation(c, android.R.anim.fade_in); 
        anim_out.setAnimationListener(new AnimationListener()
        {
            @Override public void onAnimationStart(Animation animation) {}
            @Override public void onAnimationRepeat(Animation animation) {}
            @Override public void onAnimationEnd(Animation animation)
            {
                v.setImageBitmap(new_image); 
                anim_in.setAnimationListener(new AnimationListener() {
                    @Override public void onAnimationStart(Animation animation) {}
                    @Override public void onAnimationRepeat(Animation animation) {}
                    @Override public void onAnimationEnd(Animation animation) {}
                });
                v.startAnimation(anim_in);
            }
        });
        v.startAnimation(anim_out);
    }
3
répondu radhoo 2013-01-06 15:16:54

J'ai utilisé l'animation FADEIN utilisée pour remplacer la nouvelle image par l'ancienne

ObjectAnimator.ofFloat(imageView, View.ALPHA, 0.2f, 1.0f).setDuration(1000).start();
3
répondu Rafael 2015-01-17 10:57:09

Le meilleur et le plus facile, pour moi, c'était ça..

- > créez simplement un thread avec un gestionnaire contenant sleep ().

private ImageView myImageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_shape_count); myImageView= (ImageView)findViewById(R.id.shape1);
    Animation myFadeInAnimation = AnimationUtils.loadAnimation(this, R.anim.fadein);
    myImageView.startAnimation(myFadeInAnimation);

    new Thread(new Runnable() {
        private Handler handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                Log.w("hendler", "recived");
                    Animation myFadeOutAnimation = AnimationUtils.loadAnimation(getBaseContext(), R.anim.fadeout);
                    myImageView.startAnimation(myFadeOutAnimation);
                    myImageView.setVisibility(View.INVISIBLE);
            }
        };

        @Override
        public void run() {
            try{
                Thread.sleep(2000); // your fadein duration
            }catch (Exception e){
            }
            handler.sendEmptyMessage(1);

        }
    }).start();
}
2
répondu Sankar Behera 2016-11-20 20:41:38

J'utilise ce genre de routine pour enchaîner les animations par programmation.

    final Animation anim_out = AnimationUtils.loadAnimation(context, android.R.anim.fade_out); 
    final Animation anim_in  = AnimationUtils.loadAnimation(context, android.R.anim.fade_in); 

    anim_out.setAnimationListener(new AnimationListener()
    {
        @Override
        public void onAnimationStart(Animation animation) {}

        @Override
        public void onAnimationRepeat(Animation animation) {}

        @Override
        public void onAnimationEnd(Animation animation)
        {
            ////////////////////////////////////////
            // HERE YOU CHANGE YOUR IMAGE CONTENT //
            ////////////////////////////////////////
            //ui_image.setImage...

            anim_in.setAnimationListener(new AnimationListener()
            {
                @Override
                public void onAnimationStart(Animation animation) {}

                @Override
                public void onAnimationRepeat(Animation animation) {}

                @Override
                public void onAnimationEnd(Animation animation) {}
            });

            ui_image.startAnimation(anim_in);
        }
    });

    ui_image.startAnimation(anim_out);
1
répondu Aladin Q 2012-05-30 21:37:50

Vous pouvez le faire par deux points simples et changer votre code

1.In votre xml dans le dossier anim de votre projet, définissez la durée fade in et fade out non égale

2.In vous classe java avant le début de l'animation fade out, définissez la deuxième visibilité imageView puis après le démarrage de l'animation fade out définissez la deuxième visibilité imageView que vous voulez fondu dans visible

Fadeout.xml

<alpha
    android:duration="4000"
    android:fromAlpha="1.0"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:toAlpha="0.0" />

Fadein.xml

<alpha
    android:duration="6000"
    android:fromAlpha="0.0"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:toAlpha="1.0" />

Dans vous classe java

Animation animFadeOut = AnimationUtils.loadAnimation(this, R.anim.fade_out);
    ImageView iv = (ImageView) findViewById(R.id.imageView1);
    ImageView iv2 = (ImageView) findViewById(R.id.imageView2);
    iv.setVisibility(View.VISIBLE);
    iv2.setVisibility(View.GONE);
    animFadeOut.reset();
    iv.clearAnimation();
    iv.startAnimation(animFadeOut);

    Animation animFadeIn = AnimationUtils.loadAnimation(this, R.anim.fade_in);
    iv2.setVisibility(View.VISIBLE);
    animFadeIn.reset();
    iv2.clearAnimation();
    iv2.startAnimation(animFadeIn);
1
répondu Hadi Samadbin 2017-01-11 13:48:25

C'est probablement la meilleure solution que vous obtiendrez. Simple et facile. Je l'ai appris sur udemy. Supposons que vous ayez deux images ayant respectivement id1 et id2 d'ID d'image et que la vue de l'image soit définie comme id1 et que vous souhaitiez la changer en l'autre image chaque fois que quelqu'un clique dessus. C'est donc le code de base dans MainActivity.java File

int clickNum=0;
public void click(View view){
clickNum++;
ImageView a=(ImageView)findViewById(R.id.id1);
ImageView b=(ImageView)findViewById(R.id.id2);
if(clickNum%2==1){
  a.animate().alpha(0f).setDuration(2000); //alpha controls the transpiracy
}
else if(clickNum%2==0){
  b.animate().alpha(0f).setDuration(2000); //alpha controls the transpiracy
}

}

J'espère que cela va sûrement aider

1
répondu Saurabh Kumar 2017-12-31 16:09:57

Pour infini fondu dans et Hors

AlphaAnimation fadeIn=new AlphaAnimation(0,1);

AlphaAnimation fadeOut=new AlphaAnimation(1,0);


final AnimationSet set = new AnimationSet(false);

set.addAnimation(fadeIn);
set.addAnimation(fadeOut);
fadeOut.setStartOffset(2000);
set.setDuration(2000);
imageView.startAnimation(set);

set.setAnimationListener(new Animation.AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) { }
    @Override
    public void onAnimationRepeat(Animation animation) { }
    @Override
    public void onAnimationEnd(Animation animation) {
        imageView.startAnimation(set);
    }
});
1
répondu Aryan Sharma 2018-09-01 18:18:40