Search code examples
androidanimationandroid-custom-viewondrawdrawrectangle

Animation duration does not work


I'm creating a custom view which is basically a Rectangle (RectF object). I would like that according to a specified value by the user, to change the rectangle size accordingly with animation. So I've tried that:

public class ObjectView extends View {

public int mCanvasWidth;
public int mCanvasHeight;

public int mVolumeHeight = 0;

public RectF mObjectHead;
public RectF mObjectBody;
public RectF mObjectBodyVolume;
public Canvas mCanvas;

private boolean mInitDone = false;

public ObjectView(Context context) {
    super(context);
}

public ObjectView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public void init()
{

}

@Override
protected void onDraw(Canvas canvas)
{
    super.onDraw(canvas);
    this.mCanvas = canvas;
    float objectHeadDistanceFromLeft = mCanvasWidth / 3;
    float objectHeadWidth = mCanvasWidth / 3;

    float objectBodyDistanceFromTop = mCanvasHeight / 5;
    float objectHeadHeight = mCanvasHeight / 5;
    mBatteryHead = new RectF(batteryHeadDistanceFromLeft,0,2*objectHeadWidth,objectHeadHeight+5);
    Paint objectHeadPaint = new Paint();
    objectHeadPaint.setColor(ContextCompat.getColor(getContext(), R.color.batifyColor));
    canvas.drawRect(mObjectHead,objectHeadPaint);

    mObjectBody = new RectF(0,(int)objetBodyDistanceFromTop,mCanvasWidth,mCanvasHeight);
    Paint objectBodyPaint = new Paint();
    objectBodyPaint.setStyle(Paint.Style.STROKE);
    objectBodyPaint.setColor(ContextCompat.getColor(getContext(), R.color.batifyColor));
    objectBodyPaint.setStrokeWidth(10);
    canvas.drawRect(mObjectBody,objectBodyPaint);

    mObjectBodyVolume = new RectRectF(12, (int) objectBodyDistanceFromTop + 10, mCanvasWidth - 12, mVolumeHeight);
    Paint volumeBodyPaint = new Paint();
    volumeBodyPaint.setColor(ContextCompat.getColor(getContext(), R.color.batifyColor));
    canvas.drawRect(mObjectBodyVolume, volumeBodyPaint);

}


public void setStateOnObject(){
    this.mVolumeHeight = mCanvasHeight;
    ObjectAnimator animateBottom = ObjectAnimator.ofFloat(mObjectBodyVolume, "bottom", mObjectBodyVolume.bottom, this.mVolumeHeight);
    animateBottom.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {
            postInvalidate();
        }
    });
    AnimatorSet rectAnimation = new AnimatorSet();
    rectAnimation.play(animateBottom);
    rectAnimation.setDuration(10000).start();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec,heightMeasureSpec);
    mCanvasWidth = MeasureSpec.getSize(widthMeasureSpec);
    mCanvasHeight = MeasureSpec.getSize(heightMeasureSpec);
}
 }

The problem is that the size is not updating progressively as expected but directly to the final value whatever the duration time of the animation. Any idea what I'm doing wrong ?

Thanks in advance !


Solution

  • Avoid allocation and calculations in onDraw for the sake of performance

    The property bottom requires a setter. RectF does not have one. So have this

    public class AnimatableRectF extends RectF{
    
    
        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

     mObjectBodyVolume = new AnimatableRectF(12, (int) objectBodyDistanceFromTop + 10, mCanvasWidth - 12, mVolumeHeight);
    

    The animation part remains the same