What I Have
I have an arrow image (like the left one). Whe
You can use setFillAfter if you want to persist the state of your animation.
Verified Code: (You can follow my solution)
imageView.setImageResource(R.drawable.ic_arrow_up);
boolean up = true;
if (!up) {
up = true;
imageView.startAnimation(animate(up));
} else {
up = false;
imageView.startAnimation(animate(up));
}
private Animation animate(boolean up) {
Animation anim = AnimationUtils.loadAnimation(this, up ? R.anim.rotate_up : R.anim.rotate_down);
anim.setInterpolator(new LinearInterpolator()); // for smooth animation
return anim;
}
drawable/ic_arrow_up.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#3d3d3d"
android:pathData="M7.41,15.41L12,10.83l4.59,4.58L18,14l-6,-6 -6,6z"/>
</vector>
anim/rotate_up.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:fillEnabled="true">
<rotate
android:duration="200"
android:fromDegrees="-180"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="0" />
</set>
anim/rotate_down.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:fillEnabled="true">
<rotate
android:duration="200"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="180" />
</set>
I used that code. Because this will save the animation state:
android:fillAfter="true"
android:fillEnabled="true"
First of all, what is you minimum SDK requirement? In case it's at least Android 3.0, you can use the newer animation framework, and animate your Image with something like this:
imageView.animate().rotation(180).start();
About the flicker: I wouldn't reset the source image of the ImageView after the rotation, I'd just leave in the original and make sure that the rotation animation fills after the animation, leaving the image rotated. The flicker is most likely caused by the View's relayout/redraw upon changing the source image.
Further visual artifacts (flicker?) may be caused because the original-rotated image and the rotated static image might differ in a few pixels.
If I were you I'd use ViewPropertyAnimator (available from API 12). Its syntax is more straight forward IMO.
Usage would be:
toggle.animate().rotation(0.5f);
Why dont you use RotateAnimation?
create a folder named anim in res and a file named rotator.xml inside res/anim.
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="400"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360"/>
Here one complete rotation will be completed in 4000ms (4 seconds). Now add a PNG image that you want to rotate into your drawable folder. Then open res/main.xml, after removing the default textView in the layout, add an ImageView and Button into the layout. Set the src property of the ImageView as your filename of the added image, for example android:src=”@drawable/myimg” Ok, lets edit the main class. In the onClick() for the button, add the necessary code for running the animation. Check the following code.
public class AnimationActivity extends Activity {
public ImageView myImage ;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myImage = (ImageView)findViewById(R.id.imageView1);
final Animation myRotation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.rotator);
((Button)findViewById(R.id.button1)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
myImage.startAnimation(myRotation);
}
});
}
}
If you want to rotate an image by 180 degrees clockwise.
private var isExpanded = true
private fun rotateImage(view: View) {
val startAngle = if (isExpanded) 0f else 180f
ObjectAnimator.ofFloat(view, View.ROTATION, startAngle, startAngle + 180f).apply {
duration = 300
interpolator = LinearInterpolator()
start()
}
isExpanded = !isExpanded
}
Or more simply (as wrote @Alex.F):
view.animate().setDuration(300).rotationBy(180f).start()
Note that if you rotate the image many times too frequently, it doesn't stop in 0 - 180 - 360 positions. Because if you start a new animation before a previous finished, it will shift an angle.
So, a better way is written in the accepted answer. It doesn't depend on current animation state.
private var angle = 0f
angle += 180f
view.animate().setDuration(300).rotation(angle).start()