【问题标题】:Drawable Rotating around its center AndroidDrawable 围绕其中心旋转 Android
【发布时间】:2010-09-27 16:03:42
【问题描述】:

我得到以下代码的奇怪结果:

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);

指定轴点(drawable 的中心)的正确方法是什么?

【问题讨论】:

    标签: android rotation drawable


    【解决方案1】:

    觉得自己很蠢!花一些时间仔细阅读文档后让它工作:

    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);
    

    【讨论】:

    • 添加“a.setInterpolator(new LinearInterpolator());”使旋转更平滑。
    • 我想旋转 180 度但不重复。旋转后,对象将处于最终状态,我的意思是它不会回到开始位置。我该怎么做?
    • @Md Omar Faroque Anik:添加“a.setFillAfter(true);”使转换持久化和“a.setRepeatCount(0);”不重复。
    【解决方案2】:

    请注意,如果您的对象具有不对称填充(例如,左侧填充为 5 像素,右侧填充为 0 像素),这将不起作用,因为填充被视为对象的一部分。这意味着计算的中心将被偏移。

    如果您出于布局原因使用填充,则一个解决方案是使用边距而不是填充。正如 API 关于边距所说的那样:“这个空间超出了这个视图的边界。” (ViewGroup.MarginLayoutParams)

    这意味着边距不会像填充一样旋转。

    【讨论】:

    • 我如何告诉RotateAnimation 考虑保证金?
    【解决方案3】:

    因为这个问题的标题是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;
        }
    }
    

    【讨论】:

    • 什么是@AnimatorSetter?
    • 糟糕...这只是我的自定义注释。我用它来向 ProGuard 和 Android Studio 表明这个方法实际上是用于动画的。 (ObjectAnimator.ofFloat(this, "rotation", 0, 0); 在执行过程中调用setRotation)
    • 这个类需要保存在 ProGuard 中,VectorDrawable 会导致 pre Lollipop 崩溃,但除非你使用矢量绘图,否则不需要它。
    • @SteveM 您可以使用以下检查来支持 pre Lollipop (drawable instanceof VectorDrawableCompat || drawable.getClass().getSimpleName().equals("VectorDrawable")) 代替 (drawable instanceof VectorDrawable)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-08
    • 2013-12-18
    • 1970-01-01
    相关资源
    最近更新 更多