Drawable Вращение вокруг своего центра Android

Я получаю странные результаты со следующим кодом:

iv = (ImageView) findViewById(R.id.iv);
        iv.setImageResource(R.drawable.spinner_white_76);

        Animation a = new RotateAnimation(0.0f, 360.0f,
                Animation.RELATIVE_TO_SELF, iv.getDrawable()
                        .getIntrinsicWidth() / 2, Animation.RELATIVE_TO_SELF,
                iv.getDrawable().getIntrinsicHeight() / 2);
        a.setRepeatCount(-1);
        a.setDuration(1000);

        iv.startAnimation(a);

Как правильно указать точку оси (центр чертежа)?


person Sameer Segal    schedule 27.09.2010    source источник


Ответы (3)


Чувствую себя глупо! Он заработал, потратив некоторое время внимательно на чтение документации:

Animation a = new RotateAnimation(0.0f, 360.0f,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                0.5f);
        a.setRepeatCount(-1);
        a.setDuration(1000);
person Sameer Segal    schedule 27.09.2010
comment
Добавление a.setInterpolator (новый LinearInterpolator ()); делает вращение более плавным. - person Tom Quinn; 18.07.2012
comment
Я хочу повернуть на 180 градусов, но без повторения. после поворота объект будет в конечном состоянии, я имею в виду, что он не вернется в исходное положение. Как я могу это сделать? - person Omar Faroque Anik; 17.02.2015
comment
@Md Omar Faroque Anik: добавить a.setFillAfter (true); сделать преобразование постоянным и a.setRepeatCount (0); без повтора. - person Bubu; 23.03.2015

Обратите внимание, что это не сработает, если ваш объект имеет асимметричное заполнение (например, левое заполнение 5 пикселей и правое заполнение 0 пикселей), потому что заполнение считается частью объекта. Это означает, что вычисленный центр будет смещен.

Одно из решений этого - использовать поля вместо заполнения, если вы используете заполнение по причинам макета. Как сказано в API относительно полей: «Это пространство находится за пределами этого представления». (ViewGroup.MarginLayoutParams)

Это означает, что поля не будут вращаться, как отступы.

person st4r0pr4m    schedule 24.06.2011
comment
Как я могу сказать RotateAnimation учитывать маржу? - person Heiko Rupp; 29.04.2013

Поскольку заголовок для этого вопроса - Drawable, вращающийся вокруг его центра (и я искал именно его, не нашел и должен был реализовать сам), хотел бы опубликовать свое решение / ответ.

В итоге я написал настраиваемый объект для рисования, который может обернуть любой объект для рисования и разрешить его вращение. Вот код:

public class RotatableDrawable extends DrawableWrapper {

    private float rotation;
    private Rect bounds;
    private ObjectAnimator animator;
    private long defaultAnimationDuration;

    public RotatableDrawable(Resources resources, Drawable drawable) {
        super(vectorToBitmapDrawableIfNeeded(resources, drawable));
        bounds = new Rect();
        defaultAnimationDuration = resources.getInteger(android.R.integer.config_mediumAnimTime);
    }

    @Override
    public void draw(Canvas canvas) {
        copyBounds(bounds);
        canvas.save();
        canvas.rotate(rotation, bounds.centerX(), bounds.centerY());
        super.draw(canvas);
        canvas.restore();
    }

    public void rotate(float degrees) {
        rotate(degrees, defaultAnimationDuration);
    }

    public void rotate(float degrees, long millis) {
        if (null != animator && animator.isStarted()) {
            animator.end();
        } else if (null == animator) {
            animator = ObjectAnimator.ofFloat(this, "rotation", 0, 0);
            animator.setInterpolator(new AccelerateDecelerateInterpolator());
        }
        animator.setFloatValues(rotation, degrees);
        animator.setDuration(millis).start();
    }

    @AnimatorSetter
    public void setRotation(float degrees) {
        this.rotation = degrees % 360;
        invalidateSelf();
    }

    /**
     * Workaround for issues related to vector drawables rotation and scaling:
     * https://code.google.com/p/android/issues/detail?id=192413
     * https://code.google.com/p/android/issues/detail?id=208453
     */
    private static Drawable vectorToBitmapDrawableIfNeeded(Resources resources, Drawable drawable) {
        if (drawable instanceof VectorDrawable) {
            Bitmap b = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
            Canvas c = new Canvas(b);
            drawable.setBounds(0, 0, c.getWidth(), c.getHeight());
            drawable.draw(c);
            drawable = new BitmapDrawable(resources, b);
        }
        return drawable;
    }
}
person GregoryK    schedule 23.08.2016
comment
Что такое @AnimatorSetter? - person Steve M; 26.11.2016
comment
Упс ... Это просто моя аннотация. Я использую его, чтобы указать ProGuard и студии Android, что этот метод действительно используется для анимации. (ObjectAnimator.ofFloat (this, вращение, 0, 0); вызывает setRotation во время выполнения) - person GregoryK; 27.11.2016
comment
Этот класс необходимо сохранить в ProGuard, а VectorDrawable вызовет сбой в Pre Lollipop, но он не нужен, если вы не используете векторные чертежи. - person Steve M; 28.11.2016
comment
@SteveM вы можете использовать следующую проверку для поддержки pre Lollipop (вытягиваемый экземпляр VectorDrawableCompat || drawable.getClass (). GetSimpleName (). Equals (VectorDrawable)) вместо (вытягиваемый экземпляр VectorDrawable) - person GregoryK; 28.11.2016