0

I've an ObjectAnimator to rotate an image every 200 milliseconds until it reaches from 0 to 360 angle. Everything works fine, expect the duration it takes. For one cycle, the animation is running 20 to 30 milliseconds (varies on devices) more, which is 220 milliseconds instead of 200 milliseconds.

Requirement is to move an image from 360 to 0 angle. in 10seconds.

The Image initial angle is set as 360 and should reach 0 angle in 10 seconds with image moving only every 200 milliseconds.

So, i have a button when clicked , will call the rotate method with the from and to angle as

      // initial angle is 360 and should reach 0 in 10 seconds with image moving only every 200 milliseconds.
  rotate(360 , 360 - 7.2f); // from 360 to 352.8
      // to run 10000 milliseconds with 200 milliseconds interval it would take 50 cycle for animation to run
     // so the angle to move each cycle will be 360/50 = 7.2

Rotate method is called recursively , to move to next angle.

private void rotate(float fromAngle , final float toAngle){
    ImageView imageView = (ImageView) findViewById(R.id.rotate_image_view);

    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "rotation", fromAngle, toAngle);
    objectAnimator.setDuration(200);

    objectAnimator.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            Log.d(TAG , "End time " + System.currentTimeMillis());
            if(toAngle > 0) {
                float moveAngleTo = toAngle - 7.2f; // next angle position
                // round next angle to 0 if goes to negative
                if(moveAngleTo < 0){
                    moveAngleTo = 0;
                }
                rotate(toAngle , moveAngleTo);
            }
        }

        @Override
        public void onAnimationStart(Animator animation) {
            Log.d(TAG , "Start time " + System.currentTimeMillis());
        }
    });
    objectAnimator.start();
}

Expected is the total duration should be 10 seconds, but each cycle runs more than 200 milliseconds ,which adds to the total above 11 seconds (ie, 20 x 50 = 1000 milliseconds).

Libin
  • 16,967
  • 7
  • 61
  • 83
  • I'm confused. This looks like it's doing a single animation once for 200ms, not doing something "every 200ms". – Doug Stevenson Mar 03 '16 at 02:49
  • I don't think using `System.currentTimeMillis()` is the accurate way to measure the duration. It is just the estimation.and some variation is acceptable. – T D Nguyen Mar 03 '16 at 02:51
  • @DougStevenson - This is just the sample code , i execute the same animation when it ends for n times. – Libin Mar 03 '16 at 02:56
  • I'd suggest posting the *actual* code, saying what you expect it to do, then saying what it actually does instead. – Doug Stevenson Mar 03 '16 at 03:24
  • @Doug Stevenson - Added the complete code. Please let me know if you could find the issue. – Libin Mar 03 '16 at 04:07
  • If you want something to move only every 200ms, you probably don't want to use the Android animation system. Normal animations will always make a change to a view for *every frame* at 60 frames per second. If you have different requirements, you'll have to code that yourself using a Handler to schedule work when it has to be done. – Doug Stevenson Mar 03 '16 at 04:10
  • @DougStevenson - Thanks. I'll look at countdown timer to start the animation every 200 milliseconds. Do you think the countdown timer is accurate ? I noted that the first tick happens quicker than the specified countDownInterval, Any idea? – Libin Mar 03 '16 at 04:23
  • What I'm saying is that you don't want the usual Animation, since that always tries to work with each frame. You can just schedule work every 200ms to make an adjustment to the view that should happen at the current time offset from when the whole thing started. – Doug Stevenson Mar 03 '16 at 04:27
  • Yes it got it . Thanks. Do you recommend using `CountDownTimer` to schedule work for every 200ms? – Libin Mar 03 '16 at 04:30

1 Answers1

0

Try following code:

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mView, "rotation", fromAngle, toAngle);

    objectAnimator.setDuration(200);
    objectAnimator.setRepeatCount(ObjectAnimator.INFINITE);
    objectAnimator.setRepeatMode(ObjectAnimator.RESTART);
    objectAnimator.setInterpolator(new AccelerateInterpolator());

    objectAnimator.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            LogUtil.d(TAG , "End time " + System.currentTimeMillis());
        }

        @Override
        public void onAnimationStart(Animator animation) {
            LogUtil.d(TAG , "Start time " + System.currentTimeMillis());
        }
        @Override
        public void onAnimationRepeat(Animator animation) {
            animation.setInterpolator(new LinearInterpolator());
        }
    });
Rakesh
  • 756
  • 1
  • 9
  • 19