Android绘制动画虚线

Android绘制动画虚线,android,animation,bezier,Android,Animation,Bezier,我已经在这方面工作了好几天,但没有找到一个好的解决方案(至少对我来说) 基本上,我需要做的是画一条动画虚线,这将代表一个基本游戏的导弹轨迹。该轨迹将接受起始、中间和最终的x,y。刚开始的时候,我读了很多关于曲线甚至直线动画的Q/a,但与我必须做的事情相比,它们看起来非常复杂 我有一个按钮,上面有一个onclick监听器,可以触发导弹发射,但直到现在它只画静态线,没有任何动画 你还记得这个吗?这就是我想要实现的目标: 香蕉轨迹没有画出来,但是,你有这个想法 在这里,再次从您的示例开始,我尝试使

我已经在这方面工作了好几天,但没有找到一个好的解决方案(至少对我来说)

基本上,我需要做的是画一条动画虚线,这将代表一个基本游戏的导弹轨迹。该轨迹将接受起始、中间和最终的x,y。刚开始的时候,我读了很多关于曲线甚至直线动画的Q/a,但与我必须做的事情相比,它们看起来非常复杂

我有一个按钮,上面有一个
onclick
监听器,可以触发导弹发射,但直到现在它只画静态线,没有任何动画

你还记得这个吗?这就是我想要实现的目标:

香蕉轨迹没有画出来,但是,你有这个想法


在这里,再次从您的示例开始,我尝试使用数组和for循环同时绘制曲线,但我得到的结果是,有时,并非总是,应用程序会因nullpointer异常而崩溃,我不知道为什么。我做错了什么?这是我的密码:

public class DrawDottedCurve extends View {

    Path[] path = new Path[8];
    Path[] drawingPath = new Path[8];
    PathMeasure[] measure = new PathMeasure[8];
    Path[] segmentPath = new Path[8];
    float[] length = new float[8];
    float[] start = new float[8];
    float[] percent = new float[8];
    Paint paint = new Paint();
    float x1;
    float y1;
    float x3;
    float y3;
    long k = 0;
    Canvas canvas;
    Random r = new Random();

    public DrawDottedCurve(Context context, int a, int b, int c, int d) {
        super(context);
        x1 = a;
        y1 = b;
        x3 = c;
        y3 = d;

        paint.setAlpha(255);
        paint.setStrokeWidth(2);
        paint.setColor(Color.RED);
        paint.setStyle(Style.STROKE);
        paint.setPathEffect(new DashPathEffect(new float[] { 2, 4 }, 50));

        for (int i = 0; i < 8; i++) {
            k = r.nextInt(100 - 30) + 30;
            path[i] = new Path();
            path[i].moveTo(x1 + k, y1 + k); //
            path[i].quadTo((x3 + k - x1 + k) / 2, (y3 + k - y1 + k) / 2,
                    x3 + k, y3 + k); // Calculate Bezier Curves
        }

        final long DRAW_TIME = 10000;
        CountDownTimer timer = new CountDownTimer(DRAW_TIME, 100) {

            @Override
            public void onTick(long millisUntilFinished) {
                Log.d("Timer", "Inizio");
                for (int i = 0; i < 8; i++) {
                    start[i] = 0;
                    measure[i] = new PathMeasure();
                    measure[i].setPath(path[i], false);

                    percent[i] = ((float) (DRAW_TIME - millisUntilFinished))
                            / (float) DRAW_TIME;

                    segmentPath[i] = new Path();
                    drawingPath[i] = new Path();
                    length[i] = measure[i].getLength() * percent[i];
                    measure[i].getSegment(start[i], length[i], segmentPath[i],
                            true);
                    start[i] = length[i];
                    drawingPath[i].addPath(segmentPath[i]);


                }
                invalidate();
;
            }

            @Override
            public void onFinish() {
                for (int i = 0; i < 8; i++) {
                    measure[i].getSegment(start[i], measure[i].getLength(),
                            segmentPath[i], true);
                    drawingPath[i].addPath(segmentPath[i]);


                }

                invalidate();   
                Log.d("Timer", "Fine");
            }

        };
        timer.start();
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < 8; i++) {
            canvas.drawPath(drawingPath[i], paint);
            invalidate();

        }

    }
}
公共类DrawDottedCurve扩展视图{
路径[]路径=新路径[8];
路径[]drawingPath=新路径[8];
PathMeasure[]measure=新的PathMeasure[8];
路径[]分段路径=新路径[8];
浮动[]长度=新浮动[8];
浮动[]开始=新浮动[8];
浮动[]百分比=新浮动[8];
油漆=新油漆();
浮点x1;
浮动y1;
浮动x3;
浮动y3;
长k=0;
帆布;
随机r=新随机();
公共DrawDottedCurve(上下文、int a、int b、int c、int d){
超级(上下文);
x1=a;
y1=b;
x3=c;
y3=d;
油漆。setAlpha(255);
油漆。设置行程宽度(2);
油漆。设置颜色(颜色。红色);
油漆.设置样式(样式.笔划);
setPathEffect(新的DashPathEffect(新的float[]{2,4},50));
对于(int i=0;i<8;i++){
k=r.nextInt(100-30)+30;
路径[i]=新路径();
路径[i]。移动到(x1+k,y1+k)//
路径[i].四通((x3+k-x1+k)/2,(y3+k-y1+k)/2,
x3+k,y3+k);//计算贝塞尔曲线
}
最终长抽时间=10000;
倒计时计时器=新倒计时计时器(绘图时间,100){
@凌驾
公共void onTick(长毫秒未完成){
Log.d(“计时器”、“IO”);
对于(int i=0;i<8;i++){
开始[i]=0;
measure[i]=新路径measure();
度量[i]。设置路径(路径[i],false);
百分比[i]=((浮动)(绘制时间-毫秒)
/(浮动)绘制时间;
分段路径[i]=新路径();
drawingPath[i]=新路径();
长度[i]=度量值[i].getLength()*百分比[i];
度量[i].getSegment(开始[i],长度[i],段路径[i],
正确的);
起始[i]=长度[i];
drawingPath[i].addPath(segmentPath[i]);
}
使无效();
;
}
@凌驾
公共无效onFinish(){
对于(int i=0;i<8;i++){
度量值[i]。getSegment(开始[i],度量值[i]。getLength(),
分段路径[i],真);
drawingPath[i].addPath(segmentPath[i]);
}
使无效();
Log.d(“计时器”、“罚款”);
}
};
timer.start();
}
@凌驾
公共空白onDraw(画布){
super.onDraw(帆布);
对于(int i=0;i<8;i++){
canvas.drawPath(drawingPath[i],paint);
使无效();
}
}
}

假设您有一个画布可供绘制,并且您希望跟踪此代码的路径,则应该为其制作动画

private void init() {
    missilePath = new Path();
    missileDrawPath = new Path();

    mPaint = new Paint();
    mPaint.setStrokeWidth(3);
    mPaint.setColor(Color.BLACK);
    mPaint.setStyle(Style.STROKE);
    mPaint.setAntiAlias(true);

    PathEffect dashEffect = new DashPathEffect(new float[] {2, 4}, 0);
    mPaint.setPathEffect(dashEffect);

    final long DRAW_TIME = 5000;
    timer = new CountDownTimer(DRAW_TIME, 100) {
        PathMeasure measure = new PathMeasure();
        Path segmentPath = new Path();
        float start = 0;

        @Override
        public void onTick(long millisUntilFinished) {
            measure.setPath(missilePath, false);
            float percent = ((float) (DRAW_TIME - millisUntilFinished)) / (float) DRAW_TIME;
            float length = measure.getLength() * percent;
            measure.getSegment(start, length, segmentPath, true);
            start = length;
            missileDrawPath.addPath(segmentPath);
            invalidate();
        }

        @Override
        public void onFinish() {
            measure.getSegment(start, measure.getLength(), segmentPath, true);
            missileDrawPath.addPath(segmentPath);
            invalidate();
        }
    };
    timer.start();
}


@Override
public void onDraw(Canvas c) {
    super.onDraw(c);
    c.drawPath(missileDrawPath, mPaint);
}

基本上,计时器会启动,根据所用的时间,从
missilePath
中检索一个段,并将其添加到当前应绘制的路径中。

谢谢SceLus,它工作得非常好,下面是最终陷入同一问题的人的完整代码

类构造函数以Bezier曲线的起点和终点x和y作为输入,简单地计算中间控制点,然后根据SceLus代码绘制所有内容

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.os.CountDownTimer;
import android.view.View;

public class DrawDottedCurve extends View {

    Path path = new Path();
    Path drawingPath = new Path();
    Paint paint = new Paint();
    float x1;
    float y1;
    float x3;
    float y3;

    public DrawDottedCurve(Context context, int a, int b, int c, int d) {
        super(context);

        x1 = a;
        y1 = b;
        x3 = c;
        y3 = d;

        paint.setAlpha(255);
        paint.setStrokeWidth(2);
        paint.setColor(Color.RED);
        paint.setStyle(Style.STROKE);
        paint.setPathEffect(new DashPathEffect(new float[] { 2, 4 }, 50));

        path.moveTo(x1, y1); //
        path.quadTo((x3 - x1) / 2, (y3 - y1) / 2, x3, y3); // Calculate Bezier Curve

        final long DRAW_TIME = 10000;
        CountDownTimer timer = new CountDownTimer(DRAW_TIME, 100) {
            PathMeasure measure = new PathMeasure();
            Path segmentPath = new Path();
            float start = 0;

            @Override
            public void onTick(long millisUntilFinished) {
                measure.setPath(path, false);
                float percent = ((float) (DRAW_TIME - millisUntilFinished))
                        / (float) DRAW_TIME;
                float length = measure.getLength() * percent;
                measure.getSegment(start, length, segmentPath, true);
                start = length;
                drawingPath.addPath(segmentPath);
                invalidate();
            }

            @Override
            public void onFinish() {
                measure.getSegment(start, measure.getLength(), segmentPath,
                        true);
                drawingPath.addPath(segmentPath);
                invalidate();
            }
        };
        timer.start();
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawPath(drawingPath, paint);
    }
}

计算曲线上的点,例如贝塞尔曲线,然后一个接一个地画出来……我将在接下来的几天内实现代码,并让您知道。现在谢谢你