web-dev-qa-db-de.com

Wie zeichnet man einen Pfad auf einer Android-Leinwand mit Animation?

Ich mache eine Android-App und ich habe eine schwierige Sache zu tun ... Ich muss einen Pfad auf einer Leinwand zeichnen, aber die Zeichnung sollte animiert sein (dh Punkt für Punkt mit einer kurzen Verzögerung zeichnen).

Ist es möglich, so etwas mit Android SDK zu erstellen? Wenn nicht, wie könnte ich diesen Effekt erzeugen?

24
Romain Piel

Probieren Sie diesen Code aus. Ich habe damit einen Heartbeat mit Path & Canvas gezeichnet:

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

}

Dabei wird ein Pfad Punkt für Punkt mit einigen Effekten mit Hilfe von Zählern gezeichnet. Sie können nehmen, was Sie benötigen, und es an SurfaceView übertragen, was effizienter ist.

31
Hesham Saeed

Ich hoffe, das ist was Sie suchen. Es zeichnet den Weg bei der Benutzerberührung. Sie können es einfach abwinken, um das zu erreichen, was Sie wünschen.

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;

        }

    }
3
Kazekage Gaara

Dies könnte helfen ... Es zeichnet benachbarte Kreise anstelle eines Pfads, um einen animierbaren Pfad zu simulieren.

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;
  }
}
}
0
Baffled