I'm trying to make a path animation with DashPathEffect. Have to be able to replay it multiple times, using a button.
Based on http://www.curious-creature.org/2013/12/21/android-recipe-4-path-tracing/
My problem is, the animation works well the first 10 times or so, then the path goes crazy and it starts flickering, going in the reverse order or finishes where it doesn't have to.
I logged the values of the animation and the values passed to the path and they look correct, no jumps or anything weird. I have no idea what is causing the issues.
This is the code:
public class Test extends View {
private float mDrag;
private MyPath path1;
private int mDuration;
//just some shape
private static Path makeDragPath(int radius) {
Path p = new Path();
RectF oval = new RectF(10.0f, 10.0f, radius * 2.0f, radius * 2.0f);
float cx = oval.centerX();
float cy = oval.centerY();
float rx = oval.width() / 2.0f;
float ry = oval.height() / 2.0f;
final float TAN_PI_OVER_8 = 0.414213562f;
final float ROOT_2_OVER_2 = 0.707106781f;
float sx = rx * TAN_PI_OVER_8;
float sy = ry * TAN_PI_OVER_8;
float mx = rx * ROOT_2_OVER_2;
float my = ry * ROOT_2_OVER_2;
float L = oval.left;
float T = oval.top;
float R = oval.right;
float B = oval.bottom;
p.moveTo(R, cy);
p.quadTo( R, cy + sy, cx + mx, cy + my);
p.quadTo(cx + sx, B, cx, B);
p.quadTo(cx - sx, B, cx - mx, cy + my);
p.quadTo(L, cy + sy, L, cy);
p.quadTo( L, cy - sy, cx - mx, cy - my);
p.quadTo(cx - sx, T, cx, T);
return p;
}
public Test(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public static class MyPath {
private static final Region sRegion = new Region();
private static final Region sMaxClip = new Region(
Integer.MIN_VALUE, Integer.MIN_VALUE,
Integer.MAX_VALUE, Integer.MAX_VALUE);
final Path path;
final Paint paint;
final float length;
final Rect bounds;
MyPath(Path path, Paint paint) {
this.path = path;
this.paint = paint;
PathMeasure measure = new PathMeasure(path, false);
this.length = measure.getLength();
sRegion.setPath(path, sMaxClip);
bounds = sRegion.getBounds();
}
}
private static PathEffect createPathEffect2(float pathLength, float phase) {
//I modified the original approach using phase, to use only path instead because later I want to animate also the starting point and phase alone is not enough for this
float full = phase * pathLength;
return new DashPathEffect(new float[] {full, Float.MAX_VALUE}, //on, off
0);
}
ObjectAnimator current;
public void startAnim() {
if (current != null) {
current.cancel();
}
current = ObjectAnimator.ofFloat(Test.this, "drag", 0.0f, 1.0f).setDuration(mDuration);
current.start();
}
private void scalePath(Path path, float scale) {
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(scale, scale);
path.transform(scaleMatrix);
}
private void init() {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(8.0f);
paint.setColor(0xffffffff);
mDuration = 3000;
Path p1 = makeDragPath(40);
scalePath(p1, 3);
path1 = new MyPath(p1, paint);
startAnim();
}
public float getDrag() {
return mDrag;
}
public void setDrag(float drag) {
mDrag = drag;
path1.paint.setPathEffect(createPathEffect2(path1.length, mDrag));
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLACK); //doesn't help
canvas.drawPath(path1.path, path1.paint);
}
}
In my activity:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
final Test test = (Test)findViewById(R.id.test);
Button button = (Button)findViewById(R.id.startTest);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
test.startAnim();
}
});
}
xml:
<Button
android:id="@+id/startTest"
android:layout_width="200dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_height="60dp" />
<com.example.ivanschuetzd.myapplication.Test
android:id="@+id/test"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:background="#000000"
/>
Any idea? Or maybe a different approach to make this kind of animation with an arbitrary path? Thanks!