我正在尝试制作可以重复几次(或无限次)的简单动画
似乎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);
它进行一个循环然后结束。
它会向上扩展,然后按比例缩小然后停止
如何按预期方式开展此工作?
答案 0 :(得分:62)
更新:早在2011年9月,一位Android工程师在很大程度上解决了这个问题。 XML中被忽略的属性现在可以工作,但repeatCount
和fillEnabled
除外,它们仍被忽略(出于某种原因故意)。这意味着遗憾的是,重复AnimationSet
仍然不容易。
有关详细信息,请参阅updated docs中的概述(解释忽略哪些属性,哪些属性有效,哪些属性传递给子级)。要更深入地了解fillAfter
,fillBefore
和fillEnabled
实际执行的操作,请参阅工程师(Chet Haase)关于它的博客文章here。
为了扩展Pavel和其他人的答案:<set>
标签确实是一个荒谬的错误。它无法正确处理repeatCount
和其他一些属性。
我花了几个小时搞清楚它能做什么和不能处理什么,并在这里提交了一个错误报告/问题:Issue 17662
总结(这涉及AnimationSet
s):
setRepeatCount()/ android:repeatCount
此属性(以及repeatMode)在代码或XML中不起作用。这使得重复整套动画变得困难。
setDuration()/ android:duration
在代码WORKS中的AnimationSet上设置此项(覆盖子动画的所有持续时间),但不包含在XML中的标记中
setFillAfter()/ android:fillAfter
这适用于标记的代码和XML。奇怪的是,我已经让它也可以在不需要将fillEnabled设置为true的情况下工作。
setFillBefore()/ android:fillBefore
似乎在代码和XML中都没有效果/忽略
setFillEnabled()/ android:fillEnabled
似乎在代码和XML中都没有效果/被忽略。即使没有包含fillEnabled或将fillEnabled设置为false,我仍然可以使fillAfter工作。
setStartOffset()/ android:startOffset
这仅适用于代码,而不适用于XML。
答案 1 :(得分:42)
我发现&lt; set&gt; 标记在 AnimationSet 类中有错误的实现。
它无法正确处理 repeatCount
我们可以做的是直接在&lt; scale&gt; 标记中设置 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"
/>
不幸的是,这仅限于一次只有一个动画
我们不能用这种方式定义一系列动画......
答案 2 :(得分:38)
您应该包含属性
android:repeatCount="infinite"
但是在你的“比例”动画中没有“设置”
答案 3 :(得分:31)
要获得重复动画,我使用了动画侦听器,并在结束时再次调用动画。这样就可以像带有括号的动画一样聚焦相机标线。
这是动画布局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);
}
答案 4 :(得分: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"/>
答案 5 :(得分:8)
你可以试试这段代码。 在您的代码中添加,
firstAnimation.setRepeatCount(5);
这将重复动画一段时间
firstAnimation.setRepeatCount(Animation.INFINITE);
firstAnimation.setRepeatMode(Animation.INFINITE);
这会无限期地重复动画。
答案 6 :(得分:2)
你必须在我下面建议的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>
答案 7 :(得分: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代表重复次数。
答案 8 :(得分:2)
使用android sdk版本4.0.3:
在给定的动画元素中:
机器人:repeatCount = “ - 1”
使它成为无限动画。
答案 9 :(得分:2)
我尝试使用Daniel的代码来显示动画的确切次数并遇到问题:当预期n次时,动画显示近似n / 2次。
所以我修改了丹尼尔的代码:
//...
@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);
}
}
}
}
//...
使用变量,如上所示,动画显示为REPEAT_COUNT次,因为View.post()方法可以在完成与上一个动画相关的所有动作后启动新动画。
答案 10 :(得分:1)
我得到了这个...我试图让视图连续旋转一圈。
之前我使用的是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();
答案 11 :(得分:1)
我以编程方式完成了我的大部分工作,但是我可能会迟到或效率低但是这个但是我完成了重复动画集目标(我甚至有2个交替的动画集)。所有这些代码都只是淡入一个图像,暂停,然后淡出,淡入另一个图像,暂停,淡出,并带回第一个(冲洗和重复)。我首先定义了我的Imageview:
final ImageView purple = (ImageView)findViewById(R.id.purp);
final ImageView yellow = (ImageView)findViewById(R.id.yell);
purple.setVisibility(View.INVISIBLE);
yellow.setVisibility(View.INVISIBLE);
然后我制作了两个计时器,任务计时器和处理程序来处理何时开始和停止每个动画:
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);
最后,我不是通过添加动画创建动画集,而是通过动画监听器来确定何时开始每个动画:
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
}
});
}
清除并使之前的尝试无效,并让这件事正常工作。我不知道他们是否需要。
希望这有助于某人。
赖安
答案 12 :(得分:1)
我在项目中使用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"
/>
答案 13 :(得分:0)
我在处理向后兼容的应用时遇到了这个问题。真令人沮丧!我最终编写了一个很好的解决方法类,可以从onCreate调用,并将任何动画资源启动到一个无限循环。
这个类,AnimationLooper,可以在这里找到: https://gist.github.com/2018678
答案 14 :(得分:0)
我已经解决了这个问题。这是我的修复版本:
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) {
}
}
}
答案 15 :(得分:0)
我遇到了同样的问题,但是由于UI线程有时可能非常繁忙,因此不希望在Java中执行任何计时工作。 INFINITE标志不适用于set标签。所以我用一小段代码解决了这个问题:
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。
答案 16 :(得分:0)
通过对互联网的回答进行研究后,我找到了一个适合我的解决方案。 (是的,当与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>
活动中: (通过在动画结束后引入一点延迟来解决它。)
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:
答案 17 :(得分:0)
需要先监听第一个动画的完成情况,然后在onStopAnimation回调中重新启动动画,试试这个link
答案 18 :(得分:0)
对@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);
答案 19 :(得分:0)
我使用线程解决了这个问题。
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
}
});
答案 20 :(得分:0)
它工作正常
GifDrawable gifDrawable = (GifDrawable) gifImageView.getDrawable();
gifDrawable.setLoopCount(0);
答案 21 :(得分:0)
以上解决方案均无法解决我的问题。 Danuofr的解决方案确实适用于动画集,但是当我进行单元测试时,我的测试过去常常陷入无限循环。最后,具体到我的情况,我需要重复这个动画特定的次数。所以,我手动在anim_rot.xml中以级联的方式添加我的动画副本添加偏移值。我知道它很糟糕并且不会为许多人工作,但这是我案件的唯一解决方法。
anim_rot.xml
restTemplate.postForObject(apiUri.toString(), command, BigDecimal.class);
我这样做是为了重复动画3次。您可以通过添加偏移值来添加更多副本以重复特定时间。
答案 22 :(得分:-1)
尝试将代码添加到循环线程或while / for语句