Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically rotate drawable or view

Could anyone tell me how they have got RotateDrawable to work whether it be from code or XML or both? The documentation on animating Drawables is pretty poor and animation only seems to work for images. I want to be able to animate all drawables. When i tried to get a RotateDrawble from XML is just causes an exception. What is the correct function to find a RotateDrawable from XML?

like image 570
D-Dᴙum Avatar asked May 03 '11 15:05

D-Dᴙum


5 Answers

The following code rotates an ImageView around its center:

ImageView myImageView = (ImageView)findViewById(R.id.my_imageview);

AnimationSet animSet = new AnimationSet(true);
animSet.setInterpolator(new DecelerateInterpolator());
animSet.setFillAfter(true);
animSet.setFillEnabled(true);

final RotateAnimation animRotate = new RotateAnimation(0.0f, -90.0f,
    RotateAnimation.RELATIVE_TO_SELF, 0.5f, 
    RotateAnimation.RELATIVE_TO_SELF, 0.5f);

animRotate.setDuration(1500);
animRotate.setFillAfter(true);
animSet.addAnimation(animRotate);

myImageView.startAnimation(animSet);
like image 94
jlopez Avatar answered Oct 20 '22 02:10

jlopez


here's a nice solution for putting a rotated drawable for an imageView:

Drawable getRotateDrawable(final Bitmap b, final float angle) {
    final BitmapDrawable drawable = new BitmapDrawable(getResources(), b) {
        @Override
        public void draw(final Canvas canvas) {
            canvas.save();
            canvas.rotate(angle, b.getWidth() / 2, b.getHeight() / 2);
            super.draw(canvas);
            canvas.restore();
        }
    };
    return drawable;
}

usage:

Bitmap b=...
float angle=...
final Drawable rotatedDrawable = getRotateDrawable(b,angle);
root.setImageDrawable(rotatedDrawable);

another alternative:

private Drawable getRotateDrawable(final Drawable d, final float angle) {
    final Drawable[] arD = { d };
    return new LayerDrawable(arD) {
        @Override
        public void draw(final Canvas canvas) {
            canvas.save();
            canvas.rotate(angle, d.getBounds().width() / 2, d.getBounds().height() / 2);
            super.draw(canvas);
            canvas.restore();
        }
    };
}

also, if you wish to rotate the bitmap, but afraid of OOM, you can use an NDK solution i've made here

like image 41
android developer Avatar answered Oct 20 '22 02:10

android developer


You have to animate the "level" property, where 0 is the start value and 10000 is the end value.

The below example animates from start to finish, you can reverse the animation easily with this method.

final RotateDrawable rotateDrawable = ...
ObjectAnimator.ofInt(rotateDrawable, "level", 0, 10000).start();
like image 20
Mark Hetherington Avatar answered Oct 20 '22 03:10

Mark Hetherington


I would like to add a full example of animating a progress icon on ImageView, it is based on Mark Hetherington answer.

So my animation looks as follows:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
                 android:pivotX="50%"
                 android:pivotY="50%"
                 android:fromDegrees="0"
                 android:toDegrees="-360"
                 android:duration="100"
                 android:drawable="@drawable/ic_loop_black_24dp"
    />

icon comes from https://material.io/icons/

then my layout contains an ImageView as follows:

        <ImageView
            android:id="@+id/progress"
            android:layout_marginTop="0dp"
            android:layout_marginLeft="-3dp"
            android:layout_width="30dp"
            android:layout_height="30dp"

            android:visibility="gone"
            android:scaleType="fitCenter"
            android:background="@drawable/progress_anim"
            android:layout_gravity="center_horizontal|center_vertical"
            />

and finally in code when I need to show animation I do:

    RotateDrawable rotateDrawable = ((RotateDrawable)progressImage.getBackground());
    ObjectAnimator anim = ObjectAnimator.ofInt(rotateDrawable, "level", 0, 10000);
    anim.setDuration(1000);
    anim.setRepeatCount(ValueAnimator.INFINITE);
    anim.start();
like image 22
marcinj Avatar answered Oct 20 '22 04:10

marcinj


RotateDrawable does not seem to be animated. Instead, you have to use setLevel to change the rotation of the drawable.

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/your_drawable"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="360" />

And set the level will rotate the drawable:

final ImageView image = (ImageView)findViewById(R.id.imageView1);
final RotateDrawable drawable = (RotateDrawable)image.getDrawable();
drawable.setLevel(500);
like image 35
Carson Reinke Avatar answered Oct 20 '22 02:10

Carson Reinke