Drawable Rotating около центъра си 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(new 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

Обърнете внимание, че това няма да работи, ако вашият обект има асиметрична подложка (например лява подложка от 5px и дясна подложка от 0px), тъй като подложката се счита за част от обекта. Което означава, че изчисленият център ще бъде изместен.

Едно решение за това е да използвате полета вместо подложка, ако използвате подложка по причини, свързани с оформлението. Както 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 studio, че този метод всъщност се използва за анимация. (ObjectAnimator.ofFloat(this, rotation, 0, 0); извиква setRotation по време на изпълнение) - person GregoryK; 27.11.2016
comment
Този клас трябва да се запази в ProGuard и VectorDrawable ще причини срив в pre Lollipop, но нямате нужда от него, освен ако не използвате векторни чертежи. - person Steve M; 28.11.2016
comment
@SteveM можете да използвате следната проверка, за да поддържате pre Lollipop (drawable instanceof VectorDrawableCompat || drawable.getClass().getSimpleName().equals(VectorDrawable)) вместо (drawable instanceof VectorDrawable) - person GregoryK; 28.11.2016