Androidanimation不重复
我试图做简单的animation,将重复几次(或无限)。
看来, android:repeatCount
不起作用!
以下是来自/res/anim/first_animation.xml
animation资源:
<?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中被忽略的属性现在可以工作,除了repeatCount
和fillEnabled
,它们仍然被忽略(出于某种原因)。 这意味着不幸的是重复一个AnimationSet
并不容易。
有关详细信息,请参阅更新文档中的概述(说明忽略哪些属性,哪些工作以及哪些属性传递给子节点)。 而为了更深入的了解fillAfter
, fillBefore
和fillEnabled
究竟是做什么的,请看这里的工程师(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次。 您可以添加更多副本,通过添加偏移值来重复特定时间。