Android Animate Rectangle in Custom View

android, animation, rect, view

Solution

According to the documentation the property need a setter in the class you are applying the animator.

This name will be used to derive a setter function that will be called to set animated values.

The point is that Rect doesn't have a setWidth() or a setHeight().

Moreover Rect doesn't have a width and height property, by the way you can animate its four coordinates (`top`, `left`, `right`, `bottom`) and achieve the effect you need. (just consider width as `Math.abs(left - right)` and height as `Math.abs(top - bottom)`).

In order to have it working on a Rect (or a RectF like in the example below - if you need it on a Rect just use int setters instead of floats) you need to subclass it by adding the setters of the property you will need:

private class AnimatableRectF extends RectF{
        public AnimatableRectF() {
            super();
        }

        public AnimatableRectF(float left, float top, float right, float bottom) {
            super(left, top, right, bottom);
        }

        public AnimatableRectF(RectF r) {
            super(r);
        }

        public AnimatableRectF(Rect r) {
            super(r);
        }

        public void setTop(float top){
            this.top = top;
        }
        public void setBottom(float bottom){
            this.bottom = bottom;
        }
        public void setRight(float right){
            this.right = right;
        }
        public void setLeft(float left){
            this.left = left;
        }

    }

Then you can animate it the normal way... here an example to animate an AnimatableRectF called mCurrentRect to perform a translation:

float translateX = 50.0f;
float translateY = 50.0f;
ObjectAnimator animateLeft = ObjectAnimator.ofFloat(mCurrentRect, "left", mCurrentRect.left, mCurrentRect.left+translateX);
ObjectAnimator animateRight = ObjectAnimator.ofFloat(mCurrentRect, "right", mCurrentRect.right, mCurrentRect.right+translateX);
ObjectAnimator animateTop = ObjectAnimator.ofFloat(mCurrentRect, "top", mCurrentRect.top, mCurrentRect.top+translateY);
ObjectAnimator animateBottom = ObjectAnimator.ofFloat(mCurrentRect, "bottom", mCurrentRect.bottom, mCurrentRect.bottom+translateY);
animateBottom.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                        @Override
                        public void onAnimationUpdate(ValueAnimator valueAnimator) {
                            postInvalidate();
                        }
                    });
AnimatorSet rectAnimation = new AnimatorSet();
rectAnimation.playTogether(animateLeft, animateRight, animateTop, animateBottom);
rectAnimation.setDuration(1000).start();

I know it's not a copy/paste solution to solve your problem but I hope this code will help you to understand how to fix your issue!

Problem

I have created a class that extends `View` which I shall reference within a layout for it to be drawn on the screen. This class simply represents a Rectangle where I wish to make the length of the rectangle decrease all the way to 0. Constructor: ``` public CardAnimationNew(Context context, AttributeSet attrs) { super(context, attrs); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(getResources().getColor(R.color.card_grey_underline)); } ``` onMeasure: ``` @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mRectangle == null) { mWidth = getMeasuredWidth(); mHeight = getMeasuredHeight(); mRectangle = new Rect(0, 0, mWidth, mHeight); animateRectangle(); } } ``` animateRectangle: ``` private void animateRectangle() { mObjectAnimator = ObjectAnimator.ofFloat(mRectangle, "width", 5); mObjectAnimator.setDuration(1000); mObjectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { invalidate(); } }); mObjectAnimator.start(); } ``` onDraw: ``` @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawRect(mRectangle, mPaint); } ``` The problem is that the `Rect` isn't animating at all. It stays the same length. Where am I going wrong?

Original source

Related problems