安卓动画不重复播放

87

我正在尝试制作一个简单的动画,它会重复几次(或者无限循环)。
看起来 android:repeatCount 不起作用!
这是我的动画资源,位于 /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>

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

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

它完成一次循环,然后停止。
它会缩放,然后再缩小,最后停止。

我该如何让其按照意图工作?


你的Java代码中,imgView是什么? - clifgray
23个回答

64
更新:2011年9月,一位Android工程师大部分修复了这个问题。在XML中被忽略的属性现在可以使用,除了repeatCountfillEnabled仍然被忽略(因为某种原因而故意这样做)。这意味着遗憾的是,重复一个AnimationSet仍然不容易。
有关详细信息,请参见更新文档中的总览(解释哪些属性被忽略,哪些起作用以及哪些传递给子级)。有关fillAfterfillBeforefillEnabled实际作用的更深入理解,请参见工程师(Chet Haase)的博客文章here
原始答案:
要扩展Pavel和其他人的答案:确实,<set>标记存在严重的错误。它无法正确处理repeatCount和许多其他属性。
我花了几个小时弄清楚它能够处理和不能处理的内容,并在此处提交了一个错误报告/问题:Issue 17662
总之(这涉及到AnimationSet):
setRepeatCount() / android:repeatCount
此属性(以及repeatMode)在代码或XML中均不起作用。这使得重复整个动画集变得困难。
setDuration() / android:duration
在代码中将其设置为一个AnimationSet可以工作(覆盖所有子动画的持续时间),但是在XML的中包含时不能正常工作。
setFillAfter() / android:fillAfter 在标签的代码和XML中都可以工作。奇怪的是,我还成功地在不需要将fillEnabled设置为true的情况下使其工作。
setFillBefore() / android:fillBefore 似乎在代码和XML中都没有效果/被忽略。
setFillEnabled() / android:fillEnabled
似乎在代码和XML中都没有效果/被忽略。即使未包括fillEnabled或将其设置为false,我仍然可以使fillAfter工作。
setStartOffset() / android:startOffset
仅在代码中工作,而不是XML中。

51

我发现在 AnimationSet 类中,<set> 标签的实现存在缺陷。
它不能正确处理 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"
/>

很遗憾,这只限于一次动画。
我们不能以这种方式定义一个动画序列...


我正在运行一组中的两个动画,它们没有给我任何问题。请告诉我你在谈论哪个问题?哪个错误?目前正在使用1.6 SDK进行工作。 - AZ_
在XML中声明repeatCount是有效的,但在代码中不起作用。 - onmyway133

41

你应该包含该属性

android:repeatCount="infinite"

但是在你的“scale”动画中,而不是在“set”中。


1
但是这些动画会等待前面的动画完成吗?谢谢。 - filthy_wizard
谢谢,这个方法可行!以编程方式设置它出了点问题。 - cherry-wave
谢谢!这个可行。但它是连续的。是否可以每5秒钟发生一次? - d34th4ck3r

32

我使用动画监听器获取循环动画,并在其完成后再次调用动画。 这个动画类似于括号的相机准星聚焦。

这是动画布局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);
}

2
是的,这应该是正确的答案。适用于所有设备和操作系统级别。 - Smeet
它也帮助了我,但我从End方法中删除了这两行代码:Animation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this, R.anim.crosshair_focusing); anim.setAnimationListener(this); - aida

10
我之前也遇到了同样的问题.. 我在XML文件中加入了android:repeatCount="infinite",现在它正常工作了...
  <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"/>


9
您可以尝试这段代码。在您的代码中添加以下内容:
firstAnimation.setRepeatCount(5);

这将会以一定的时间重复动画。
firstAnimation.setRepeatCount(Animation.INFINITE);
firstAnimation.setRepeatMode(Animation.INFINITE);

这将无限重复动画。

4
repeatMode 应该是 RESTART 或者 REVERSE - xinthink
这正是我想要的,被动态设置为无限大。 - Varun Chaudhary
2
setRepeat不起作用,根据https://code.google.com/p/android/issues/detail?id=17662。 - ElliotM

4

我尝试使用Daniel的代码来确切地展示动画n次,但是出现了问题:只显示了大约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);
            }
        }  
    } 
}
//... 

使用上面展示的 variant,动画将会被准确地重复播放 REPEAT_COUNT 次,因为 View.post() 方法能够在前一个动画相关的所有操作完成后启动新的动画。

3
您需要在我下面建议的xml代码中添加一行。
<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>

3

我之前在我的项目中使用 android:repeatMode="reverse" 解决了这个问题。

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

2
将以下类添加到您的项目中:
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 a = AnimationUtils(Context, R.anim.animation);
new AnimationRepeater(View, a, int N).start();

N代表重复次数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接