Search code examples
javaandroidtimerandroid-canvasthread-sleep

Android Canvas transition from white to red


I am trying to transition the canvas from white to red however it seems to never draw till the very end. So you cannot see the transition. I have tried a few options using Timer and other Java utilities however they always require the variables to be final which is not possible. I believe using thread sleep is the best approach however I do not get the desired output.

for(int i=0; i < 255; i++){
    try {
        Thread.sleep(10);
        paint.setARGB(255,i,0,0);
        canvas.drawPaint(paint);
        invalidate();
    } catch(InterruptedException ex) {
        Thread.currentThread().interrupt();
    }
}

As you can see the for loop will loop through 0 - 255 and sets the paint's argb accordingly. The canvas get's painted and invalidate() is called. There is a slight delay of 10 for the Thread.sleep() method.

I have not found a nice way to accomplish this in android canvas and this I think is my current implementation. For the few seconds delay there is nothing and then at the end just the final color of argb(255,255,0,0). When it should be showing every color from argb(255,0,0,0) - argb(255,255,0,0).


Solution

  • Use ValueAnimator for this like below

    class CustomView extends AnyView {
    
      ...
    
      public void setBackgroundColor(int color){
        paint.setColor(color);
        invalidate();
      }
    
      public void animateColorChange(int startColor, int endColor) {
       ValueAnimator anim = ValueAnimator.ofInt(startColor, endColor); 
        anim.setEvaluator(new ArgbEvaluator());
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                final int newColor = (int) animator.getAnimatedValue();
                setBackgroundColor(newColor);
            } });
    
        anim.start();
      }
    
     public void onDraw(Canvas canvas) {
        canvas.drawPaint(paint);
      }
    }
    

    Or replace ValueAnimator with ObjectAnimator

    ObjectAnimator anim = ObjectAnimator.ofObject(paint, "color", new ArgbEvaluator(), startColor, endColor);
    anim.setDuration(1500);
    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
      @Override
      public void onAnimationUpdate(ValueAnimator animation) {
        invalidate();
      }
    });
    
    anim.start();