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?
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With