J'essaie de faire une animation simple qui se répéterait plusieurs fois (ou à l'infini).
Il semble que android:repeatCount
cela ne fonctionne pas!
Voici ma ressource d'animation de /res/anim/first_animation.xml
:
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
android:repeatCount="infinite"
>
<scale
android:interpolator="@android:anim/decelerate_interpolator"
android:duration="500"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="1.2"
android:toYScale="1.2"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false" />
<scale
android:interpolator="@android:anim/accelerate_interpolator"
android:startOffset="500"
android:duration="500"
android:fromXScale="1.2"
android:fromYScale="1.2"
android:toXScale="1.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false" />
</set>
Tout d'abord, il doit redimensionner l'image de 1,0 à 1,2 taille en 500 ms.
Et puis redimensionnez-le à 1,0 en 500 ms.
Voici comment je l'utilise:
Animation firstAnimation = AnimationUtils.loadAnimation(this, R.anim.first_animation);
imgView.startAnimation(firstAnimation);
Il fait un cycle puis se termine.
Il augmente, puis diminue et s'arrête.
Comment puis-je faire en sorte que cela fonctionne comme prévu?
Réponses:
Mise à jour: en septembre 2011, un ingénieur Android a résolu ce problème en grande partie. Les attributs ignorés dans XML fonctionnent désormais, à l'exception de
repeatCount
etfillEnabled
qui sont toujours ignorés (volontairement pour une raison quelconque). Cela signifie qu'il n'est toujours pas facile de répéter unAnimationSet
malheureusement.Pour plus de détails, veuillez consulter la présentation dans la documentation mise à jour (explique quels attributs sont ignorés, lesquels fonctionnent et lesquels sont transmis aux enfants). Et pour une compréhension plus approfondie de ce que
fillAfter
,fillBefore
etfillEnabled
fait réellement, consultez le blog de l'ingénieur (Chet Haase) à ce sujet ici .Réponse originale
Pour développer les réponses de Pavel et d'autres: il est vrai que le
<set>
tag est ridiculement bogué. Il ne peut pas traiter correctementrepeatCount
et un certain nombre d'autres attributs.J'ai passé quelques heures à déterminer ce qu'il peut et ne peut pas gérer et j'ai soumis un rapport de bogue / problème ici: Problème 17662
En résumé (cela concerne
AnimationSet
les):la source
J'ai trouvé que la balise <set> a une implémentation boguée dans la classe AnimationSet .
Il ne peut pas traiter correctement repeatCount .
Ce que nous pouvons faire - est de définir repeatCount directement dans la balise <scale> .
Cette ressource XML fonctionne bien:
<?xml version="1.0" encoding="utf-8"?> <scale xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:duration="200" android:fromXScale="1.0" android:fromYScale="1.0" android:toXScale="1.05" android:toYScale="1.05" android:pivotX="50%" android:pivotY="50%" android:repeatMode="reverse" android:fillAfter="false" android:repeatCount="24" />
Malheureusement, cela est limité à une seule animation à la fois.
On ne peut pas définir une séquence d'animations de cette façon ...
la source
Vous devez inclure l'attribut
android:repeatCount="infinite"
Mais dans votre animation "échelle" pas dans "ensemble"
la source
Pour obtenir une animation répétée, j'ai utilisé l'écouteur d'animation et j'ai appelé à nouveau l'animation à la fin. Cela fait une mise au point du réticule de caméra comme une animation avec des crochets.
Voici la mise en page de l'animation xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <scale android:fromXScale="1.0" android:toXScale=".7" android:fromYScale="1.0" android:pivotX="50%" android:pivotY="50%" android:toYScale=".7" android:duration="1000"/> <scale android:duration="1000" android:fromXScale=".7" android:toXScale="1.0" android:fromYScale=".7" android:pivotX="50%" android:pivotY="50%" android:toYScale="1.0" android:startOffset="1000"/> </set>
Voici le code java
public void startAnimation() { View brackets = findViewById(R.id.brackets); brackets.setVisibility(View.VISIBLE); Animation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this, R.anim.crosshair_focusing); anim.setAnimationListener(new AnimationListener() { @Override public void onAnimationEnd(Animation arg0) { Animation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this, R.anim.crosshair_focusing); anim.setAnimationListener(this); brackets.startAnimation(anim); } @Override public void onAnimationRepeat(Animation arg0) { // TODO Auto-generated method stub } @Override public void onAnimationStart(Animation arg0) { // TODO Auto-generated method stub } }); brackets.startAnimation(anim); }
la source
J'étais également confronté au même problème .. j'ai inclus android: repeatCount = "infinite" dans le fichier XMl..Maintenant ça fonctionne bien ...
<translate android:fromXDelta="0" android:toXDelta="80" android:duration="1000" android:repeatCount="infinite" android:repeatMode="reverse" android:pivotX="50%" android:pivotY="50%" android:fillAfter="true"/>
la source
vous pouvez essayer ce code. Dans votre code, ajoutez simplement,
firstAnimation.setRepeatCount(5);
Cela répétera l'animation pendant un temps défini
firstAnimation.setRepeatCount(Animation.INFINITE); firstAnimation.setRepeatMode(Animation.INFINITE);
Cela répétera l'animation indéfiniment.
la source
repeatMode
devrait être soitRESTART
ouREVERSE
J'ai essayé d'utiliser le code de Daniel pour afficher l'animation le nombre exact de fois et j'ai eu un problème: l'animation était montrée approximativement n / 2 fois, alors que n fois prévu.
J'ai donc modifié le code de Daniel:
//... @Override public void onAnimationEnd(Animation arg0) { mCurrentCount++; if (mCurrentCount < REPEAT_COUNT) { Animation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this, R.anim.crosshair_focusing); anim.setAnimationListener(this); brackets.post(new Runnable() { @Override public void run() { brackets.startAnimation(anim); } } } } //...
En utilisant la variante, illustrée ci-dessus, l'animation est affichée exactement REPEAT_COUNT fois, car la méthode View.post () donne la possibilité de démarrer une nouvelle animation après avoir terminé toutes les actions, liées à l'animation précédente.
la source
vous devez ajouter une seule ligne dans votre code xml que j'ai suggéré ci-dessous.
<scale android:duration="500" android:fromXScale="1.0" android:fromYScale="1.0" android:toXScale="1.2" android:toYScale="1.2" android:pivotX="50%" android:pivotY="50%" android:repeatCount="infinite" // just add this one line android:fillAfter="false" /> </set>
la source
J'ai résolu ce problème en utilisant
android:repeatMode="reverse"
avant dans mon projet.<scale android:interpolator="@android:anim/decelerate_interpolator" android:duration="500" android:fromXScale="1.0" android:fromYScale="1.0" android:toXScale="1.2" android:toYScale="1.2" android:pivotX="50%" android:pivotY="50%" android:repeatMode="reverse" android:repeatCount="infinite" />
la source
Avec la version 4.0.3 d'Android SDK:
Dans les éléments d'animation donnés:
android: repeatCount = "- 1"
en fait une animation infinie.
la source
Ajoutez la classe suivante à votre projet:
import android.view.View; import android.view.animation.Animation; public class AnimationRepeater implements Animation.AnimationListener { private View view; private Animation animation; private int count; public AnimationRepeater(View view, Animation animation) { this.view = view; this.animation = animation; this.count = -1; } public AnimationRepeater(View view, Animation animation, int count) { this.view = view; this.animation = animation; this.count = count; } public void start() { this.view.startAnimation(this.animation); this.animation.setAnimationListener(this); } @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { if (this.count == -1) this.view.startAnimation(animation); else { if (count - 1 >= 0) { this.animation.start(); count --; } } } @Override public void onAnimationRepeat(Animation animation) { } }
Pour une boucle infinie de votre vue, procédez comme suit:
Animation a = AnimationUtils(Context, R.anim.animation); new AnimationRepeater(View, a).start();
Si vous souhaitez répéter l'animation pour N fois uniquement, procédez comme suit:
Animation a = AnimationUtils(Context, R.anim.animation); new AnimationRepeater(View, a, int N).start();
N représente le nombre de répétitions.
la source
Je fais la plupart de mes trucs par programmation et je suis peut-être en retard ou inefficace sur celui-ci, mais j'ai atteint l'objectif de répétition d'animations (j'ai même 2 jeux d'animations en alternance). Tout ce que ce code fait est simplement de fondre dans une image, de mettre en pause, puis de disparaître, de fondre dans une autre image, de mettre en pause, de disparaître et de ramener la première (rincer et répéter). J'ai d'abord défini mes vues d'image:
final ImageView purple = (ImageView)findViewById(R.id.purp); final ImageView yellow = (ImageView)findViewById(R.id.yell); purple.setVisibility(View.INVISIBLE); yellow.setVisibility(View.INVISIBLE);
Ensuite, j'ai créé deux minuteries, des minuteries de tâches et des gestionnaires pour savoir quand démarrer et arrêter chaque animation:
Timer p = new Timer(); TimerTask pu = new TimerTask() { public void run() { handler1.post(new Runnable() { public void run() { fadein(purple); } }); }}; p.schedule(pu, 6000, 12000); final Handler handler2 = new Handler(); Timer y = new Timer(); TimerTask ye = new TimerTask() { public void run() { handler2.post(new Runnable() { public void run() { fadein(yellow); } }); }}; y.schedule(ye, 0, 12000);
Enfin, plutôt que de créer des ensembles d'animations en ajoutant des animations, je me contente d'animations pour les écouteurs pour déterminer quand démarrer chaque animation:
public void fadein (final ImageView image) { Animation anim = new AlphaAnimation(0, 1); anim.setDuration(2000); image.startAnimation(anim); anim.setAnimationListener(new AnimationListener() { public void onAnimationEnd(Animation animation) { image.clearAnimation(); image.invalidate(); pause(image); } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } }); } public void pause (final ImageView image) { Animation anim = new AlphaAnimation(1, 1); anim.setDuration(2000); image.startAnimation(anim); anim.setAnimationListener(new AnimationListener() { public void onAnimationEnd(Animation animation) { image.clearAnimation(); image.invalidate(); fadeout(image); } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } }); } public void fadeout (final ImageView image) { Animation anim = new AlphaAnimation(1,0); anim.setDuration(2000); image.startAnimation(anim); anim.setAnimationListener(new AnimationListener() { public void onAnimationEnd(Animation animation) { image.clearAnimation(); image.invalidate(); } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } }); }
La clearanimation et invalider où juste les tentatives précédentes et faire fonctionner cette chose correctement. Je ne sais pas s'ils sont nécessaires ou non.
J'espère que cela aide quelqu'un.
Ryan
la source
J'ai eu ça pour aller ... J'essayais d'obtenir une vue pour tourner en cercle en continu.
précédent j'utilisais rotation.setRepeatMode (-1) mais cela ne fonctionnait pas. commuté sur setrepeatcount et cela fonctionne. C'est sur Jelly Bean 4.2.2
ObjectAnimator rotation = ObjectAnimator.ofFloat(myview, "rotation", 360).setDuration(2000); rotation.setRepeatMode(-1); rotation.setRepeatCount(Animation.INFINITE); rotation.start();
la source
J'ai rencontré le même problème, mais je ne voulais pas faire de choses de chronométrage en Java à cause du fait que le thread de l'interface utilisateur peut parfois être très occupé. L'indicateur INFINITE ne fonctionne pas pour la balise set. J'ai donc résolu le problème avec un petit morceau de code:
mAnimation = (AnimationSet) AnimationUtils.loadAnimation(myContext, R.anim.blink); mIcon.startAnimation(mAnimation); mAnimation.setAnimationListener(new AnimationListener() { public void onAnimationStart(Animation animation) {} public void onAnimationRepeat(Animation animation) {} public void onAnimationEnd(Animation animation) { mIcon.startAnimation(mAnimation); } });
avec le XML suivant:
<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:fromAlpha="0.0" android:toAlpha="1.0" /> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:fromAlpha="0.9" android:startOffset="1000" android:toAlpha="0.0" />
Où mIcon est un ImageView de ma mise en page.
la source
J'ai résolu ce problème. Voici ma version du correctif:
public class HelloAndroidActivity extends Activity { private static String TAG = "animTest"; private Animation scaleAnimation; private int currentCover = 0; private List<ImageView> imageViews = new ArrayList<ImageView>(3); private Button btn; private ImageView img; /** * Called when the activity is first created. * @param savedInstanceState If the activity is being re-initialized after * previously being shut down then this Bundle contains the data it most * recently supplied in onSaveInstanceState(Bundle). <b>Note: Otherwise it is null.</b> */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i(TAG, "onCreate"); setContentView(R.layout.test); img = (ImageView)findViewById(R.id.testpict); imageViews.add(img); img = (ImageView)findViewById(R.id.testpictTwo); imageViews.add(img); img = (ImageView)findViewById(R.id.testpict3); imageViews.add(img); scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.photo_scale); scaleAnimation.setAnimationListener(new CyclicAnimationListener()); btn = (Button)findViewById(R.id.startBtn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { imageViews.get(0).startAnimation(scaleAnimation); } }); } private class CyclicAnimationListener implements AnimationListener{ @Override public void onAnimationEnd(Animation animation) { currentCover += 1; if(currentCover >= imageViews.size()){ currentCover = 0; } img = imageViews.get(currentCover); scaleAnimation = AnimationUtils.loadAnimation(HelloAndroidActivity.this, R.anim.photo_scale); scaleAnimation.setAnimationListener(new CyclicAnimationListener()); img.startAnimation(scaleAnimation); } @Override public void onAnimationRepeat(Animation animation) { Log.d("Animation", "Repeat"); } @Override public void onAnimationStart(Animation animation) { } } }
la source
Je viens de rencontrer ce problème en travaillant sur une application rétrocompatible. tellement frustrant! J'ai fini par coder une belle classe de contournement qui peut être appelée depuis onCreate et lancera toute ressource d'animation dans une boucle indéfinie.
la classe, AnimationLooper, est disponible ici: https://gist.github.com/2018678
la source
Après avoir recherché les réponses sur Internet, j'ai trouvé une solution qui fonctionne parfaitement pour moi. (Et oui, repeatCount et repeatMode sont extrêmement bogués lorsqu'ils sont utilisés avec animationSet).
anim_rotate_fade.xml:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:ordering="together" > <objectAnimator android:duration="3000" android:propertyName="rotation" android:repeatCount="1" android:valueTo="360" android:valueType="floatType" /> <objectAnimator android:duration="3000" android:propertyName="alpha" android:repeatCount="1" android:repeatMode="reverse" android:valueFrom="0.0" android:valueTo="0.3" android:valueType="floatType" /> <objectAnimator android:duration="3000" android:propertyName="y" android:repeatCount="1" android:repeatMode="reverse" android:valueFrom="380" android:valueTo="430" android:valueType="floatType" /> </set>
En activité: (Résolvez-le en introduisant un léger délai après la fin de l'animation).
ImageView starlightImageView = new ImageView(this); starlightImageView.setImageResource(R.drawable.starlight); final AnimatorSet animate = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.anim.anim_rotate_fade); AnimatorListenerAdapter animatorListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); new Handler().postDelayed(new Runnable() { @Override public void run() { animate.start(); } }, 1000); } }; animate.setTarget(starlightImageView); animate.addListener(animatorListener);
Il y a beaucoup de classes sur lesquelles vous aimeriez faire des recherches, mais actuellement j'utilise objectAnimator qui est très flexible. Je ne recommanderais pas d'utiliser Animation ou AnimationUtils:
la source
Il faut écouter la fin de la première animation, puis redémarrer l'animation dans le rappel onStopAnimation, essayez ce lien
la source
Petite modification de la réponse @Danufr pour éviter que les ressources ne se rechargent.
operator = (ImageView) findViewById(R.id.operator_loading); final Animation ani = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.finding_operator); ani.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { operator.startAnimation(ani); } @Override public void onAnimationRepeat(Animation animation) { } }); operator.setAnimation(ani);
la source
J'ai résolu ce problème en utilisant le fil.
Button btn = (Button) findViewById(R.id.buttonpush); final TextView textview = (TextView) findViewById(R.id.hello); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { textview.setText("..................."); final Animation animationtest = AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.slide_in_left); animationtest.setDuration(1000); final Handler handler = new Handler(); Runnable runnable = new Runnable() { public void run() { handler.postDelayed(this, 1500); textview.startAnimation(animationtest); } }; handler.postDelayed(runnable, 500); // start handler.removeCallbacks(runnable); //STOP Timer } });
la source
ça marche bien
GifDrawable gifDrawable = (GifDrawable) gifImageView.getDrawable(); gifDrawable.setLoopCount(0);
la source
Aucune des solutions ci-dessus n'a fonctionné dans mon cas. La solution de Danuofr fonctionnait pour le jeu d'animation, mais lorsque je faisais des tests unitaires, mes tests étaient bloqués dans cette boucle infinie. Enfin, spécifique à mon cas, j'avais besoin de répéter cette animation un certain nombre de fois. J'ai donc ajouté manuellement des copies de mon animation dans anim_rot.xml en cascade en ajoutant la valeur de décalage . Je sais que c'est mauvais et ne fonctionnera pas pour beaucoup, mais c'était la seule solution de contournement pour mon cas.
anim_rot.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"> <rotate android:duration="2000" android:fromDegrees="20" android:pivotX="29%" android:pivotY="50%" android:toDegrees="-20" /> <rotate android:duration="2000" android:fromDegrees="-20" android:pivotX="29%" android:pivotY="53%" android:startOffset="2000" android:toDegrees="20" /> <rotate android:startOffset="4000" android:duration="2000" android:fromDegrees="20" android:pivotX="29%" android:pivotY="56%" android:toDegrees="-20" /> <rotate android:duration="2000" android:fromDegrees="-20" android:pivotX="29%" android:pivotY="59%" android:startOffset="6000" android:toDegrees="20" /> <rotate android:startOffset="8000" android:duration="2000" android:fromDegrees="20" android:pivotX="29%" android:pivotY="62%" android:toDegrees="-20" /> <rotate android:duration="2000" android:fromDegrees="-20" android:pivotX="29%" android:pivotY="65%" android:startOffset="10000" android:toDegrees="20" /> </set>
J'ai fait cela pour répéter l'animation 3 fois. Vous pouvez ajouter d'autres copies pour le répéter à des moments spécifiques en ajoutant des valeurs de décalage.
la source
Essayez d'ajouter le code à un thread en boucle ou à une instruction while / for
la source