How to make a smooth image rotation in Android?

267,586

Solution 1

You are right about AccelerateInterpolator; you should use LinearInterpolator instead.

You can use the built-in android.R.anim.linear_interpolator from your animation XML file with android:interpolator="@android:anim/linear_interpolator".

Or you can create your own XML interpolation file in your project, e.g. name it res/anim/linear_interpolator.xml:

<?xml version="1.0" encoding="utf-8"?>
<linearInterpolator xmlns:android="http://schemas.android.com/apk/res/android" />

And add to your animation XML:

android:interpolator="@anim/linear_interpolator"

Special Note: If your rotate animation is inside a set, setting the interpolator does not seem to work. Making the rotate the top element fixes it. (this will save your time.)

Solution 2

I had this problem as well, and tried to set the linear interpolator in xml without success. The solution that worked for me was to create the animation as a RotateAnimation in code.

RotateAnimation rotate = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotate.setDuration(5000);
rotate.setInterpolator(new LinearInterpolator());

ImageView image= (ImageView) findViewById(R.id.imageView);

image.startAnimation(rotate);

Solution 3

This works fine

<?xml version="1.0" encoding="UTF-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1600"
    android:fromDegrees="0"
    android:interpolator="@android:anim/linear_interpolator"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:toDegrees="358" />

To reverse rotate:

<?xml version="1.0" encoding="UTF-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1600"
    android:fromDegrees="358"
    android:interpolator="@android:anim/linear_interpolator"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:toDegrees="0" />

Solution 4

Maybe, something like this will help:

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        imageView.animate().rotationBy(360).withEndAction(this).setDuration(3000).setInterpolator(new LinearInterpolator()).start();
    }
};

imageView.animate().rotationBy(360).withEndAction(runnable).setDuration(3000).setInterpolator(new LinearInterpolator()).start();

By the way, you can rotate by more than 360 like:

imageView.animate().rotationBy(10000)...

Solution 5

Try using toDegrees="359" since 360° and 0° are the same.

Share:
267,586

Related videos on Youtube

emmby
Author by

emmby

Author of Android Application Development for Dummies. Author of RoboGuice, as well as the OpenTable, TripIt, and Digg Android applications. bebop Mobile at Google http://about.me/michaelburton

Updated on November 27, 2021

Comments

  • emmby
    emmby over 2 years

    I'm using a RotateAnimation to rotate an image that I'm using as a custom cyclical spinner in Android. Here's my rotate_indefinitely.xml file, which I placed in res/anim/:

    <?xml version="1.0" encoding="UTF-8"?>
    <rotate
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:fromDegrees="0"
        android:toDegrees="360"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="infinite"
        android:duration="1200" />    
    

    When I apply this to my ImageView using AndroidUtils.loadAnimation(), it works great!

    spinner.startAnimation( 
        AnimationUtils.loadAnimation(activity, R.anim.rotate_indefinitely) );
    

    The one problem is that the image rotation seems to pause at the top of every cycle.

    In other words, the image rotates 360 degrees, pauses briefly, then rotates 360 degrees again, etc.

    I suspect that the problem is that the animation is using a default interpolator like android:iterpolator="@android:anim/accelerate_interpolator" (AccelerateInterpolator), but I don't know how to tell it not to interpolate the animation.

    How can I turn off interpolation (if that is indeed the problem) to make my animation cycle smoothly?

  • emmby
    emmby over 14 years
    Great theory. I'm pretty sure it's not that because the speedup/slowdown is quite smooth and deliberate looking. Just in case though I tried decreasing the degrees to 358 and there was no discernible change in behavior.
  • Kingpin
    Kingpin about 13 years
    This is because interpolator was spelled wrong (no "n"). You don't need to make your own
  • Adam Rabung
    Adam Rabung over 12 years
    I've tried every interpolator available, including the linear, and i still get this little "hitch" at the beginning of every cycle.
  • shalafi
    shalafi almost 12 years
    If your rotate animation is inside a set, setting the interpolator does not seem to work. Making the rotate the top element fixes it
  • RoundSparrow hilltx
    RoundSparrow hilltx over 9 years
    For reverse, just have repeatcount 2 and set android:repeatMode="reverse" - no need to have two different XML files.
  • agonist_
    agonist_ almost 8 years
    Hey, what if you actually want to use accelerate_decelerate_interpolator without the small "pause" between every animations ?
  • XcodeNOOB
    XcodeNOOB over 7 years
    Working perfect, is imageView.clearAnimation() will clean up the runnable as well ?
  • Abhijit Jagtap
    Abhijit Jagtap about 7 years
    Its working fine for start animation, but after start runnable its not clean up by imageView.clearAnimation(), i used in touch listener event
  • behelit
    behelit about 7 years
    why 358 and not 359 or 360?
  • abggcv
    abggcv almost 7 years
    Where to add this file to in resources? Is animation a separate package for this?
  • Fonix
    Fonix almost 6 years
    if you want the animation to stay at the orientation at the end, add rotate.setFillAfter(true);
  • Pants
    Pants over 5 years
    Can't stop these runnables independently
  • Vitaly Zinchenko
    Vitaly Zinchenko over 5 years
    @Pants you can call withEndAction(this) on some condition. If the condition is false, withEndAction(this) won't be called, and animation should stop
  • Rishabh Saxena
    Rishabh Saxena over 5 years
    where is you "animation" variable declaration ?
  • ahmednabil88
    ahmednabil88 about 5 years
    if you want the animation to stay permanently with no end, addrotate.setRepeatCount(Animation.INFINITE);
  • borchvm
    borchvm about 4 years
    While this code may provide a solution to the question, it's better to add context as to why/how it works. This can help future users learn, and apply that knowledge to their own code. You are also likely to have positive feedback from users in the form of upvotes, when the code is explained.
  • smrf
    smrf over 3 years
    if you want the object to rotate infinitely, you need to set the degree from 180 to 360. also, setFillAfter as mention by Fonix is needed
  • serif
    serif almost 2 years
    comes alive with alpha