web-dev-qa-db-fra.com

l'animation Android n'est pas terminée dans onAnimationEnd

Il semble qu'une animation Android ne soit pas vraiment terminée lorsque l'événement onAnimationEnd est déclenché, bien que animation.hasEnded soit défini sur true.

Je souhaite que mon point de vue change de fond à la fin de la variable ScaleAnimation, ce qui est le cas, mais vous pouvez voir clairement que la modification est effectuée quelques millisecondes avant la fin. Le problème est qu'il scintille car le nouvel arrière-plan apparaît (= est) mis à l'échelle pendant une courte période, jusqu'à la fin de l'animation.

Existe-t-il un moyen d’obtenir la fin réelle de l’animation ou simplement d’empêcher que le nouvel arrière-plan ne soit redimensionné pendant cette courte période?

Je vous remercie!


// EDIT: J'utilise une AnimationListener pour obtenir l'appel suivant:

    @Override
public void onAnimationEnd(Animation animation)
{
    View view = (MyView) ((ExtendedScaleAnimation) animation).getView();

    view.clearAnimation();
    view.requestLayout();
    view.refreshBackground(); // <-- this is where the background gets changed
}
65
ShadowMare

Voici le bogue actuel lié à ce problème http://code.google.com/p/Android-misc-widgets/issues/detail?id=8

Cela indique essentiellement que la méthode onAnimationEnd ne fonctionne pas vraiment bien lorsqu'un AnimationListener est attaché à une Animation.

La solution de contournement consiste à écouter les événements d'animation de la vue à laquelle vous appliquiez l'animation à Par exemple, si vous attachez initialement l'écouteur d'animation à l'animation comme celle-ci. 

mAnimation.setAnimationListener(new AnimationListener() {
    @Override
    public void onAnimationEnd(Animation arg0) {
        //Functionality here
    }
});

puis appliquer à l'animation à un ImageView comme celui-ci

mImageView.startAnimation(mAnimation);

Pour contourner ce problème, vous devez maintenant créer un ImageView personnalisé.

public class MyImageView extends ImageView {

puis substituez la méthode onAnimationEnd de la classe View et fournissez toutes les fonctionnalités

@Override
protected void onAnimationEnd() {
    super.onAnimationEnd();
    //Functionality here
}

Il s'agit de la solution de contournement appropriée pour ce problème. Fournissez les fonctionnalités de la méthode View-> onAnimationEnd trop ridée, par opposition à la méthode onAnimationEnd de l'AnimationListener attachée à l'Animation.

Cela fonctionne correctement et il n'y a plus de scintillement vers la fin de l'animation. J'espère que cela t'aides.

91
Soham

Je devais résoudre ce problème en appelant clearAnimation () sur la vue animée à l'intérieur de onAnimationEnd , qui a supprimé le scintillement. été appelé que si l’animation est déjà terminée. Mais je suppose que la réponse réside dans la profondeur de Framework sur la façon dont la vue/la mise en forme gère le rappel d’animation… .. Pour l’instant, considérez-la comme une solution sans hack, qui fonctionne.

        animation.setAnimationListener(new AnimationListener() {

        public void onAnimationEnd(Animation anim) {
            innerView.clearAnimation();   // to get rid of flicker at end of animation

            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams
            (innerBlockContainer.getWidth(), innerBlockContainer.getHeight());

            /* Update lp margin, left/top to update layout after end of Translation */
            ViewGroup parent_ofInnerView = (ViewGroup)innerView.getParent();
            vp.updateViewLayout(innerBlockContainer, lp);

        }

        public void onAnimationRepeat(Animation arg0) {}

        public void onAnimationStart(Animation arg0) {
        }

    });

     innerView.startAnimation(animation);
32
lucknow_rocks

J'ai eu un problème similaire et j'ai utilisé la solution de Soham avec la classe de vue personnalisée.

Cela a bien fonctionné, mais à la fin, j’ai trouvé une solution plus simple qui a fonctionné pour moi.

Après avoir appelé view.StartAnimation(animation) et avant l'étape suivante de mon programme, j'ai ajouté un court délai qui sera suffisamment long pour laisser l'animation se terminer, mais suffisamment court pour que l'utilisateur ne puisse pas le remarquer: 

new Handler().postDelayed(new Runnable() {
       @Override
       public void run() {
           nextStepInMyProgram();
       }
     }, 200);// delay in milliseconds (200)
6
Doigen

J'ai eu le même problème et résolu en utilisant 

view.clearAnimation();

avant

view.startAnimation(anim);
5
savepopulation

Pour une raison quelconque, onAnimationStart fonctionne correctement et onAnimationEnd ne fonctionne pas. Alors voici comment je l’ai fait et ce que j’ai changé:

Tentative 1 (scintillement): A) Déplacez l'image de 0px à 80px B. Dans onAnimationEnd, définissez l'emplacement de l'image sur 80px

Tentative 2 (pas de scintillement): A) Dans onAnimationStart, définissez l'emplacement de l'image sur 80px B) Déplacez l'image de -80px à 0px

J'espère que cela avait du sens. Fondamentalement, j'ai inversé la façon dont je l'ai fait

2
Matt

Essayez d’utiliser getAnimation () à partir de votre objet:

public void onShowListBtnClick(View view)
    {
        rightPanel.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, R.anim.slide_left));

        rightPanel.getAnimation().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) {
                // write your code here
            }
        });
}
1
Butsaty

Si vous utilisez le nombre de répétitions comme infini, onAnimationEnd ne sera pas appelée. Consultez la documentation link

0
sanjeeb

l'animation peut également être arrêtée lors de la rotation de l'écran. dans ce cas, onAnimationEnd () n'est pas appelé. ma solution de contournement:

 animation.setDuration(animationDuration);
 animation.setAnimationListener(new AnimationListenerAdapter() {...});
 view.startAnimation(animation);
 handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if(!animation.hasEnded()) {
                    // here you can handle this case
                }
            }
        }, animationDuration + 100);
0
Oleg Khalidov

J'ai eu ce problème parce que ma Animation n'a pas été démarrée dans le fil principal . Cela a entraîné une duration de 0 . Cependant, la Animation a été lue correctement - elle a juste appelé onAnimationEnd() immédiatement après l'exécution.

0
Ken Van Hoeylandt

Une solution simple consiste à ajouter une ligne àAnimationListener.onAnimationEnd():

@Override 
public void onAnimationEnd(Animation a) {
    a.setAnimationListener(null);
    …
}
0
Alex Cohn