如何通过Android在画布上以恒定速度缓慢绘制几条线? [英] How to draw several lines slowly in constant velocity on canvas by Android?

查看:59
本文介绍了如何通过Android在画布上以恒定速度缓慢绘制几条线?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要捕获标记才能在Android的画布上绘制图形,其效果就像下面的gif:

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

到目前为止,我可以使用 ValueAnimator 以恒定的速度绘制侧面.但是,我一次只能绘制一个侧面,因为在绘制下一个侧面时我无法保存最后一个侧面.那么,有没有解决这个问题的好方法?

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?

ValueAnimator缓慢画线的代码:

Code for draw a line slowly by ValueAnimator:

GraphicsView.java

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

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

推荐答案

您可以使用ObjectAnimator类进行回调 每当您想绘制更多路径时,都可以使用其中一种方法.

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

然后,只需要像这样调用init()开始动画(或者,如果您希望它在视图膨胀后立即开始,请将init()调用放入构造函数中):

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

也可以在此处

使用Value Animator示例

参考1

参考2

参考文献3

这篇关于如何通过Android在画布上以恒定速度缓慢绘制几条线?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆