How to draw a path on an Android canvas with animation?

末鹿安然 提交于 2019-11-28 04:23:37

Try this code, I used it to draw a heartbeat using Path & Canvas:

public class TestActivity extends Activity {

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new HeartbeatView(this));

    }

    public static class HeartbeatView extends View {

        private static Paint paint;
        private int screenW, screenH;
        private float X, Y;
        private Path path;
        private float initialScreenW;
        private float initialX, plusX;
        private float TX;
        private boolean translate;
        private int flash;
        private Context context;


        public HeartbeatView(Context context) {
            super(context);

            this.context=context;

            paint = new Paint();
            paint.setColor(Color.argb(0xff, 0x99, 0x00, 0x00));
            paint.setStrokeWidth(10);
            paint.setAntiAlias(true);
            paint.setStrokeCap(Paint.Cap.ROUND);
            paint.setStrokeJoin(Paint.Join.ROUND);
            paint.setStyle(Paint.Style.STROKE);
            paint.setShadowLayer(7, 0, 0, Color.RED);


            path= new Path();
            TX=0;
            translate=false;

            flash=0;

        }

        @Override
        public void onSizeChanged (int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);

            screenW = w;
            screenH = h;
            X = 0;
            Y = (screenH/2)+(screenH/4)+(screenH/10);

            initialScreenW=screenW;
            initialX=((screenW/2)+(screenW/4));
            plusX=(screenW/24);

            path.moveTo(X, Y);

        }



        @Override
        public void onDraw(Canvas canvas) {
            super.onDraw(canvas);

            //canvas.save();    


            flash+=1;
            if(flash<10 || (flash>20 && flash<30))
            {
                paint.setStrokeWidth(16);
                paint.setColor(Color.RED);
                paint.setShadowLayer(12, 0, 0, Color.RED);
            }
            else
            {
                paint.setStrokeWidth(10);
                paint.setColor(Color.argb(0xff, 0x99, 0x00, 0x00));
                paint.setShadowLayer(7, 0, 0, Color.RED);
            }

            if(flash==100)
            {
                flash=0;
            }

            path.lineTo(X,Y);
            canvas.translate(-TX, 0);
            if(translate==true)
            {
                TX+=4;
            }

            if(X<initialX)
            {
                X+=8;
            }
            else
            {
                if(X<initialX+plusX)
                {
                    X+=2;
                    Y-=8;
                }
                else
                {
                    if(X<initialX+(plusX*2))
                    {
                        X+=2;
                        Y+=14;
                    }
                    else
                    {
                        if(X<initialX+(plusX*3))
                        {
                            X+=2;
                            Y-=12;
                        }
                        else
                        {
                            if(X<initialX+(plusX*4))
                            {
                                X+=2;
                                Y+=6;
                            }
                            else
                            {
                                if(X<initialScreenW)
                                {
                                    X+=8;
                                }
                                else
                                {
                                    translate=true;
                                    initialX=initialX+initialScreenW;
                                }
                            }
                        }
                    }
                }

            }

            canvas.drawPath(path, paint);


            //canvas.restore(); 

            invalidate();
        }
    }

}

It uses drawing a Path point by point with couple of effects using counters. You can take what you need and transfer it to SurfaceView which is more efficient.

I hope this is what you are looking for. It draws the path on user touch, you could simply tweek it to achieve what you desire.

public class MyCanvas extends Activity implements OnTouchListener{

        DrawPanel dp;
        private ArrayList<Path> pointsToDraw = new ArrayList<Path>();
        private Paint mPaint;
        Path path;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);
            dp = new DrawPanel(this);
            dp.setOnTouchListener(this);
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            mPaint = new Paint();
            mPaint.setDither(true);
            mPaint.setColor(Color.WHITE);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeJoin(Paint.Join.ROUND);
            mPaint.setStrokeCap(Paint.Cap.ROUND);
            mPaint.setStrokeWidth(30);

            FrameLayout fl = new FrameLayout(this);  
            fl.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));  
            fl.addView(dp);  
            setContentView(fl);  

        }

        @Override
        protected void onPause() {
            // TODO Auto-generated method stub
            super.onPause();
            dp.pause();
        }



        @Override
        protected void onResume() {
            // TODO Auto-generated method stub
            super.onResume();
            dp.resume();
        }



        public class DrawPanel extends SurfaceView implements Runnable{

            Thread t = null;
            SurfaceHolder holder;
            boolean isItOk = false ;

            public DrawPanel(Context context) {
                super(context);
                // TODO Auto-generated constructor stub
                holder = getHolder();
            }

            @Override
            public void run() {
                // TODO Auto-generated method stub
                while( isItOk == true){

                    if(!holder.getSurface().isValid()){
                        continue;
                    }

                    Canvas c = holder.lockCanvas();
                    c.drawARGB(255, 0, 0, 0);
                    onDraw(c);
                    holder.unlockCanvasAndPost(c);
                }
            }

            @Override
            protected void onDraw(Canvas canvas) {
                // TODO Auto-generated method stub
                super.onDraw(canvas);
                            synchronized(pointsToDraw)
                            {
                for (Path path : pointsToDraw) {
                    canvas.drawPath(path, mPaint);
                }
                            }
            }

            public void pause(){
                isItOk = false;
                while(true){
                    try{
                        t.join();
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                    break;
                }
                t = null;
            }

            public void resume(){
                isItOk = true;  
                t = new Thread(this);
                t.start();

            }



        }


        @Override
        public boolean onTouch(View v, MotionEvent me) {
            // TODO Auto-generated method stub
                    synchronized(pointsToDraw)
                    {
            if(me.getAction() == MotionEvent.ACTION_DOWN){
                path = new Path();
                path.moveTo(me.getX(), me.getY());
                //path.lineTo(me.getX(), me.getY());
                pointsToDraw.add(path);
            }else if(me.getAction() == MotionEvent.ACTION_MOVE){
                path.lineTo(me.getX(), me.getY());
            }else if(me.getAction() == MotionEvent.ACTION_UP){
                //path.lineTo(me.getX(), me.getY());
            }
            }       
            return true;

        }

    }

This might help... It draws adjacent circles instead of a path to simulate an animatable path.

public class PathAnimatable {
private final float CIRCLE_SIZE = 2.5f;
public float SPPED_SCALE = 1f;
private float steps = 0;
private float pathLength;
private PathMeasure pathMeasure;
private float totalStepsNeeded;
private float[] point = new float[]{0f, 0f};
private float stride;

public PathAnimatable() {
  this(null);
}

public PathAnimatable(Path path) {
  super(path);
  init();
}

private void init() {
  pathMeasure = new PathMeasure(path, false);
  pathLength = pathMeasure.getLength();
  stride = CIRCLE_SIZE * 0.5f;
  totalStepsNeeded = pathLength / stride;
  steps = 0;
}

@Override
public void setPath(Path path) {
  super.setPath(path);
  init();
}

// Called this from your locked canvas loop function
public void drawShape(Canvas canvas, Paint paint) {
  if (steps <= pathLength) {
    for (float i = 0; i < steps ; i += stride) {
      pathMeasure.getPosTan(i, point, null);
      canvas.drawCircle(point[0], point[1], CIRCLE_SIZE, paint);
    }
    steps += stride * SPPED_SCALE;
  } else {
    steps = 0;
  }
}
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!