Wednesday, July 4, 2018

How to draw several lines slowly in constant velocity on canvas by Android?

Leave a Comment

I need capture the mark to draw a figure on canvas in Android, and the effect just like the follow gif:

enter image description here

Well, as far, I can draw a side with constant velocity by ValueAnimator. However, I just only can draw one side at one time, because I can't save the last side when drawing the next side. So, is there a good way to solve the problem?

Code for draw a line slowly by ValueAnimator:

GraphicsView.java

public class GraphicsView extends View {     private int stepX, stepY = 0;     private int startX, startY, stopX, stopY = 0;     private Paint paint = null;      public GraphicsView(Context context) {         super(context);          // Paint         paint = new Paint();         paint.setAntiAlias(true);         paint.setColor(Color.RED);         paint.setStyle(Paint.Style.STROKE);          startX = 40;         startY = 397;         stopX  = 1040;          stopY  = 397;          Init();     }      public void Init(){         ValueAnimator animatorX = ValueAnimator.ofFloat(startX, stopX);         ValueAnimator animatorY = ValueAnimator.ofFloat(startY, stopY);          animatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {             @Override             public void onAnimationUpdate(ValueAnimator valueAnimator) {                 stepX = Math.round((Float)valueAnimator.getAnimatedValue()); invalidate();             }         });         animatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {             @Override             public void onAnimationUpdate(ValueAnimator valueAnimator) {                 stepY = Math.round((Float)valueAnimator.getAnimatedValue()); invalidate();             }         });          AnimatorSet set = new AnimatorSet();         LinearInterpolator l = new LinearInterpolator();         set.setInterpolator(l);         set.setDuration(3000);         set.playTogether(animatorX, animatorY);         set.start();     }      @Override     protected void onDraw(Canvas canvas) {         super.onDraw(canvas);         canvas.drawLine(startX, startY, stepX, stepY, paint);     } } 

MainActivity.java

public class MainActivity extends AppCompatActivity {        private Display display         = null;       private GraphicsView view       = null;       private ConstraintLayout layout = null;      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);          display = getWindowManager().getDefaultDisplay();         layout = (ConstraintLayout)findViewById(R.id.main_layout);          view = new GraphicsView(this);         view.setMinimumWidth(display.getWidth());         view.setMinimumHeight(display.getHeight());            layout.addView(view);     } } 

1 Answers

Answers 1

you can use the ObjectAnimator class to callback to one of your class methods every time you'd like to draw a bit more of the path.

import android.animation.ObjectAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.DashPathEffect; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PathEffect; import android.graphics.PathMeasure; import android.util.AttributeSet; import android.view.View; import android.util.Log;  public class PathView extends View {     Path path;     Paint paint;     float length;      public PathView(Context context)     {         super(context);     }      public PathView(Context context, AttributeSet attrs)     {         super(context, attrs);     }      public PathView(Context context, AttributeSet attrs, int defStyleAttr)     {         super(context, attrs, defStyleAttr);     }      public void init()     {         paint = new Paint();         paint.setColor(Color.BLUE);         paint.setStrokeWidth(10);         paint.setStyle(Paint.Style.STROKE);          path = new Path();         path.moveTo(50, 50);         path.lineTo(50, 500);         path.lineTo(200, 500);         path.lineTo(200, 300);         path.lineTo(350, 300);          // Measure the path         PathMeasure measure = new PathMeasure(path, false);         length = measure.getLength();          float[] intervals = new float[]{length, length};          ObjectAnimator animator = ObjectAnimator.ofFloat(PathView.this, "phase", 1.0f, 0.0f);         animator.setDuration(3000);         animator.start();     }      //is called by animtor object     public void setPhase(float phase)     {         Log.d("pathview","setPhase called with:" + String.valueOf(phase));         paint.setPathEffect(createPathEffect(length, phase, 0.0f));         invalidate();//will calll onDraw     }      private static PathEffect createPathEffect(float pathLength, float phase, float offset)     {         return new DashPathEffect(new float[] { pathLength, pathLength },             Math.max(phase * pathLength, offset));     }      @Override     public void onDraw(Canvas c)     {         super.onDraw(c);         c.drawPath(path, paint);     } } 

Then, just call init() to begin the animation, like this (or if you'd like it to start as soon as the view is inflated, put the init() call inside the constructors):

PathView path_view = (PathView) root_view.findViewById(R.id.path); path_view.init(); 

Also see this question here, and

Using Value Animator Example

Reference 1

Reference 2

Reference 3

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment