I want to create a rotating progress image, and wonder what's the best way to proceed. I can make it work with an animation list with for example 12 images changing every 100ms. This works fine, but it's quite tedious to create 12 images or for every size and resolution:
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/ic_loading_grey_on_black_01" android:duration="100" /> <item android:drawable="@drawable/ic_loading_grey_on_black_02" android:duration="100" /> <item android:drawable="@drawable/ic_loading_grey_on_black_03" android:duration="100" /> <item android:drawable="@drawable/ic_loading_grey_on_black_04" android:duration="100" /> <item android:drawable="@drawable/ic_loading_grey_on_black_05" android:duration="100" /> <item android:drawable="@drawable/ic_loading_grey_on_black_06" android:duration="100" /> <item android:drawable="@drawable/ic_loading_grey_on_black_07" android:duration="100" /> <item android:drawable="@drawable/ic_loading_grey_on_black_08" android:duration="100" /> <item android:drawable="@drawable/ic_loading_grey_on_black_09" android:duration="100" /> <item android:drawable="@drawable/ic_loading_grey_on_black_10" android:duration="100" /> <item android:drawable="@drawable/ic_loading_grey_on_black_11" android:duration="100" /> <item android:drawable="@drawable/ic_loading_grey_on_black_12" android:duration="100" />
I suppose that an easier solution is to use one image per resolution, but rather rotate it for each frame. In the platform resources (android-sdk-windows/platforms...) I found something called animated-rotate in the file drawable/search_spinner.xml, but if I copy the code get a compiler error complaining about android:framesCount and android:frameDuration (Google APIs 2.2 in Eclipse):
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/spinner_black_20" android:pivotX="50%" android:pivotY="50%" android:framesCount="12" android:frameDuration="100" />
I have also tried using a repeating rotate animation (using in the anim resource folder), but I actually prefer the look of the animation list version.
What is the recommended way of solving this problem?
android.view.animation.RotateAnimation. An animation that controls the rotation of an object. This rotation takes place in the X-Y plane. You can specify the point to use for the center of the rotation, where (0,0) is the top left point. If not specified, (0,0) is the default rotation point.
The animations are basically of three types as follows: Property Animation. View Animation. Drawable Animation.
To change the photo's perspective, tap Transform . Drag the dots to the edges of your desired photo or tap Auto. To rotate a photo 90 degrees, tap Rotate . To make minor adjustments to straighten the photo, use the dial above Rotate .
Rotate drawable
suggested by Praveen won't give you control of frame count. Let's assume you want to implement a custom loader which consists from 8 sections:
Using animation-list
approach, you need to create 8 frames rotated by 45*frameNumber
degrees manually. Alternatively, you can use 1st frame and set rotation animation to it:
File res/anim/progress_anim.xml
:
<?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" />
File MainActivity.java
Animation a = AnimationUtils.loadAnimation(getContext(), R.anim.progress_anim); a.setDuration(1000); imageView.startAnimation(a);
This will give you smooth animation instead of 8-stepped. To fix this we need to implement custom interpolator:
a.setInterpolator(new Interpolator() { private final int frameCount = 8; @Override public float getInterpolation(float input) { return (float)Math.floor(input*frameCount)/frameCount; } });
Also you can create a custom widget:
File res/values/attrs.xml
:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="ProgressView"> <attr name="frameCount" format="integer"/> <attr name="duration" format="integer" /> </declare-styleable> </resources>
File ProgressView.java
:
public class ProgressView extends ImageView { public ProgressView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setAnimation(attrs); } public ProgressView(Context context, AttributeSet attrs) { super(context, attrs); setAnimation(attrs); } public ProgressView(Context context) { super(context); } private void setAnimation(AttributeSet attrs) { TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ProgressView); int frameCount = a.getInt(R.styleable.ProgressView_frameCount, 12); int duration = a.getInt(R.styleable.ProgressView_duration, 1000); a.recycle(); setAnimation(frameCount, duration); } public void setAnimation(final int frameCount, final int duration) { Animation a = AnimationUtils.loadAnimation(getContext(), R.anim.progress_anim); a.setDuration(duration); a.setInterpolator(new Interpolator() { @Override public float getInterpolation(float input) { return (float)Math.floor(input*frameCount)/frameCount; } }); startAnimation(a); } }
File activity_main.xml
:
<com.example.widget.ProgressView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_progress" app:frameCount="8" app:duration="1000"/>
File res/anim/progress_anim.xml
: listed above
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With