Skip to main content

Android animation does not repeat



I'm trying to make simple animation that is repeated several times (or infinite).








It seems that android:repeatCount does not work!


Here is my animation resource from /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>







First it should scale image from 1.0 to 1.2 size in 500 ms.


And then scale it back to 1.0 in 500 ms.


Here is how I'm using it:








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

imgView.startAnimation(firstAnimation);







It makes one cycle and then finishes.


It scales up, then scales down ans then stops.





How can I make this work as intended?



Source: Tips4all

Comments

  1. To expand upon answers by Pavel and others: it is true that the <set> tag is ridiculously buggy. It can't deal correctly with repeatCount and a number of other attributes.

    I spent a few hours figuring out what it can and can't deal with and have submitted a bug report/issue here: Issue 17662

    In summary (this concerns AnimationSets):


    setRepeatCount() / android:repeatCount


    This attribute (as well as repeatMode) does not work in code or XML. This makes repeating an entire set of animations difficult.


    setDuration() / android:duration


    Setting this on an AnimationSet in code WORKS (overrides all durations of children animations), but not when included in the tag in XML


    setFillAfter() / android:fillAfter


    This works in both code and XML for the tag. Strangely I have gotten it to also work without the need to set fillEnabled to true.


    setFillBefore() / android:fillBefore


    Seems to have no effect/ignored in both code and XML


    setFillEnabled() / android:fillEnabled


    Seems to have no effect/ignored in both code and XML. I can still get fillAfter to work even without including fillEnabled or setting fillEnabled to false.


    setStartOffset() / android:startOffset


    This works only in code and not XML.

    ReplyDelete
  2. I've found that <set> tag has buggy implementation in class AnimationSet.
    It can't deal correctly with repeatCount.
    What we can do - is to set repeatCount directly in <scale> tag.

    This XML resource is working well:

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


    Unfortunately, this is limited to only one animation at once.
    We can not define a sequence of animations this way...

    ReplyDelete
  3. You should include the attribute

    android:repeatCount="infinite"


    But in your "scale" animation not in "set"

    ReplyDelete
  4. To get a repeating animation I utilized the animation listener, and called the animation again when it ended. This does a camera reticule focusing like animation with brackets.

    Here is the animation layout 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>


    Here is the java code

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

    ReplyDelete
  5. Try to add the code to a looping thread or a while/for statement

    ReplyDelete
  6. exactly, you have to put both RepeatCount and RepeatMode to infinite

    ReplyDelete
  7. I was also facing the same problem..
    i included android:repeatCount="infinite" in XMl file..now its working fine...




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

    ReplyDelete
  8. I've faced the same problem, but didn't want to do any timing things in Java because of the point that the UI thread may be very busy sometimes.
    The INFINITE flag doesn't work for the set tag. So I resolved the issue with a little piece of 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);
    }
    });


    with the following 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" />




    Where mIcon is an ImageView from my layout.

    ReplyDelete
  9. I've solved this problem. This is my version of the fix:

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

    }

    }

    }

    ReplyDelete
  10. i just came across this issue while working on a backwards compatible app. so frustrating! i ended up coding a nice workaround class that can be called from onCreate and will kickoff any animation resource into an indefinite loop.

    the class, AnimationLooper, is available here:
    https://gist.github.com/2018678

    ReplyDelete
  11. you can try this code.
    In your code just add,

    firstAnimation.setRepeatCount(5);


    This will repeat the animation for a definite time

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


    This will repeat the animation indefinitely.

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex