Androidanimation不重复

我试图做简单的animation,将重复几次(或无限)。
看来, android:repeatCount不起作用!
以下是来自/res/anim/first_animation.xmlanimation资源:

 <?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> 

首先它应该在500毫秒内将图像从1.0缩放到1.2尺寸。
然后在500毫秒内将其缩小到1.0。
这是我如何使用它:

 Animation firstAnimation = AnimationUtils.loadAnimation(this, R.anim.first_animation); imgView.startAnimation(firstAnimation); 

它使一个循环,然后完成。
它放大,然后缩小然后停止。

我怎样才能按预期做这项工作?

更新:早在2011年9月,Android工程师就解决了这个问题。 在XML中被忽略的属性现在可以工作,除了repeatCountfillEnabled ,它们仍然被忽略(出于某种原因)。 这意味着不幸的是重复一个AnimationSet并不容易。

有关详细信息,请参阅更新文档中的概述(说明忽略哪些属性,哪些工作以及哪些属性传递给子节点)。 而为了更深入的了解fillAfterfillBeforefillEnabled究竟是做什么的,请看这里的工程师(Chet Haase)博客文章。


原始答复

为了扩展Pavel和其他人的答案:确实<set>标签是可笑的。 它不能正确处理repeatCount和其他一些属性。

我花了几个小时弄清楚它能做什么,不能处理什么,并在这里提交了一个错误报告/问题: Issue 17662

总结(这涉及AnimationSet s):

setRepeatCount()/ android:repeatCount

此属性(以及repeatMode)在代码或XML中不起作用。 这使得重复一整套animation变得困难。

setDuration()/ android:持续时间

在代码WORKS的AnimationSet中设置它(覆盖子animation的所有持续时间),但不包括在XML中的标记中

setFillAfter()/ android:fillAfter

这对代码和XML都有效。 奇怪,我已经得到它也工作,而不需要将fillEnabled设置为true。

setFillBefore()/ android:fillBefore

似乎在代码和XML中都没有影响/被忽略

setFillEnabled()/ android:fillEnabled

似乎在代码和XML中都没有效果/被忽略。 即使不包含fillEnabled或将fillEnabled设置为false,我仍然可以获取fillAfter工作。

setStartOffset()/ android:startOffset

这只适用于代码而不是XML。

我发现<set>标签在类AnimationSet中有错误的实现。
它不能正确处理repeatCount
我们可以做的是直接在<scale>标签中设置repeatCount

这个XML资源运行良好:

 <?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" /> 

不幸的是,这仅限于一次animation。
我们无法以这种方式定义animation序列…

您应该包含该属性

 android:repeatCount="infinite" 

但是在你的“比例尺”animation不在“设定”

为了获得重复的animation,我使用了animation侦听器,并在结束时再次调用animation。 这是一个相机reticule像animation括号一样聚焦。

这里是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> 

这是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); } 

你可以试试这个代码。 在你的代码中只需添加,

 firstAnimation.setRepeatCount(5); 

这将重复一段时间的animation

 firstAnimation.setRepeatCount(Animation.INFINITE); firstAnimation.setRepeatMode(Animation.INFINITE); 

这将无限期地重复animation。

我也面临着同样的问题..我在XMl文件中包括android:repeatCount =“无限”..现在它的工作正常…

  <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"/> 

我试图用Daniel的代码来显示animation的确切次数,并且遇到了一个问题:animation显示的时间大约是n / 2次,当时是n次。

所以我修改了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); } } } } //... 

使用上面显示的变体,animation显示为REPEAT_COUNT次,因为View.post()方法在完成与之前animation相关的所有动作之后,可以启动新animation。

使用android sdk版本4.0.3:

在给定的animation元素中:

机器人:repeatCount = “ – 1”

使其成为无限的animation。

将以下类添加到您的项目中:

 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) { } } 

对于视图的无限循环,请执行以下操作:

 Animation a = AnimationUtils(Context, R.anim.animation); new AnimationRepeater(View, a).start(); 

如果您只想重复N次的animation,请执行以下操作:

 Animation a = AnimationUtils(Context, R.anim.animation); new AnimationRepeater(View, a, int N).start(); 

N代表重复次数。

我以编程的方式完成了我的大部分工作,但是我可能会迟到或效率低下,但是我完成了重复animation集目标(我甚至有2个交替animation集)。 所有这些代码只是淡入一个图像,暂停,然后淡出,淡入另一个图像,暂停,淡出,并带回第一个(漂洗和重复)。 我首先定义了我的Imageviews:

  final ImageView purple = (ImageView)findViewById(R.id.purp); final ImageView yellow = (ImageView)findViewById(R.id.yell); purple.setVisibility(View.INVISIBLE); yellow.setVisibility(View.INVISIBLE); 

然后,我做了两个计时器,任务计时器和处理程序来处理何时开始和停止每个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); 

最后,我不是通过添加animation来创buildanimation集,而是animation侦听器来确定何时开始每个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 } }); } 

只是以前的尝试和让这个东西正常工作的clearanimation和无效。 我不知道他们是否需要。

希望这有助于某人。


瑞安

我得到了这个去…我试图得到一个不断旋转的视图。

以前我使用rotation.setRepeatMode(-1),但没有奏效。 切换到setrepeatcount,它的工作原理。 这是在果冻豆4.2.2

  ObjectAnimator rotation = ObjectAnimator.ofFloat(myview, "rotation", 360).setDuration(2000); rotation.setRepeatMode(-1); rotation.setRepeatCount(Animation.INFINITE); rotation.start(); 

尝试将代码添加到循环线程或while / for语句

我面临同样的问题,但不想在Java中做任何计时的事情,因为有时UI线程可能非常繁忙。 INFINITE标志不适用于设置标签。 所以我用一小段代码解决了这个问题:

 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); } }); 

使用以下XML:

 <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" /> 

mIcon在我的布局中是一个ImageView。

我已经解决了这个问题。 这是我修复的版本:

 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) { } } } 

我刚刚遇到这个问题,而在向后兼容的应用程序工作。 太令人沮丧了! 我最终编写了一个可以从onCreate调用的好的解决方法类,并将任何animation资源启动到无限循环。

类AnimationLooper可以在这里find: https : //gist.github.com/2018678

通过互联网的回答,我发现了一个完美的解决scheme。 (是的,与animationSet一起使用时,repeatCount和repeatMode是非常麻烦的)。

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> 

在活动中:(通过在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); 

有很多你想研究的类,但是目前我使用的是非常灵活的objectAnimator。 我不会推荐使用animation或AnimationUtils:

  • animation
  • AnimationUtils
  • animation制作者
  • AnimatorInflater
  • AnimatorListener
  • AnimatorListenerAdapter

一个需要监听完成的第一个animation,然后在onStopAnimationcallback中重新启动animation,试试这个链接

稍微调整@Danufr答案,以节省再次加载资源。

  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); 

我之前在我的项目中解决了这个问题。

<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" />

我用线程解决了这个问题。

 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 } }); 

它工作正常

  GifDrawable gifDrawable = (GifDrawable) gifImageView.getDrawable(); gifDrawable.setLoopCount(0); 

上述解决scheme在我的情况下都不起作用。 Danuofr的解决scheme确实为animation设置工作,但是当我正在进行unit testing时,我的testing被困在这个无限循环中。 最后,针对我的情况,我需要重复这个animation特定的次数。 所以,我在anim_rot.xml中手动添加了我的animation的副本,并以级联的方式添加了偏移值 。 我知道这很糟糕,不会为很多人工作,但这是我的情况唯一的解决办法。

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> 

我做了这个重复animation3次。 您可以添加更多副本,通过添加偏移值来重复特定时间。