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?