使用DashPathEffect动画进行奇怪的闪烁

时间:2014-07-16 21:18:12

标签: android animation

我尝试使用DashPathEffect制作路径动画。必须能够使用按钮多次重播它。

基于http://www.curious-creature.org/2013/12/21/android-recipe-4-path-tracing/

我的问题是,动画在前10次左右运行良好,然后路径变得疯狂,它开始闪烁,以相反的顺序运行或完成它不必要的地方。

我记录了动画的值和传递给路径的值,它们看起来正确,没有跳跃或任何奇怪的东西。我不知道是什么导致了这些问题。

这是代码:

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);
    }

}

在我的活动中:

@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"
    />

有什么想法吗?或者可能采用不同的方法来制作具有任意路径的这种动画?谢谢!

1 个答案:

答案 0 :(得分:6)

刚刚找到了解决方案。 显然问题是DashPathEffect有点错误的硬件加速。 只需致电

setLayerType(View.LAYER_TYPE_SOFTWARE, null);
在您的视图中

应该修复它。