Animating the drawing of a canvas path on Android

2019-01-23 20:57发布

问题:

I'd like to animate the drawing of a path, i.e. to have it progressively appear on the screen. I am using the canvas and my best guess so far is to use an ObjectAnimator to take care of the animation. However, I cannot figure out how to actually draw the corresponding segment of the path in the onDraw() method. Is there a method that would allow to do this? Would I need to involve path effects for that?

Edit: Using a DashPathEffect and setting its "on" and "off" intervals in the animation to cover the part of the path we want to draw for that step seems to work here, but it requires allocating a new DashPathEffect for every step of the animation. I will leave the question open in case there is a better way.

回答1:

Answering my own question, as I figured out a satisfying way to do that.

The trick is to use an ObjectAnimator to progressively change the current length of the stroke, and a DashPathEffect to control the length of the current stroke. The DashPathEffect will have its dashes parameter initially set to the following:

float[] dashes = { 0.0f, Float.MAX_VALUE };

First float is the length of the visible stroke, second length of non-visible part. Second length is chosen to be extremely high. Initial settings thus correspond to a totally invisible stroke.

Then everytime the object animator updates the stroke length value, a new DashPathEffect is created with the new visible part and set to the Painter object, and the view is invalidated:

dashes[0] = newValue;
mPaint.setPathEffect(new DashPathEffect(dashes, 0));
invalidate();

Finally, the onDraw() method uses this painter to draw the path, which will only comprise the portion we want:

canvas.drawPath(path, mPaint);

The only drawback I see is that we must create a new DashPathEffect at every animation step (as they cannot be reused), but globally this is satisfying - the animation is nice and smooth.



回答2:

As far as I know, the only way is to start with an empty path and have a runnable that appends points to the path at defined intervals, until it is completed.