Tomb_Raider_Legend
Tomb_Raider_Legend

Reputation: 451

canvas.drawPath() is not drawing in real-time

As building upon this drawing library here, the library didn't provide a way to change stroke color or width of a single one but only changing those properties of all of the drawen strokes at the same time. So I decided to seperate each stroke with its own property to be drawen. However now the drawing stroke is not appearing in real-time when moving the finger on the screen. The whole stroke only appears upon the touch_up() function. I assume the problem is from canvas.drawPath(myPath, myPaint); in the onDraw() function but I can not manage to find what causes the problem. Does anyone know what the problem of the strokes not drawing in real-time is? Or how to fix it?

DrawingView.java:

public class DrawingView extends View {
    private Paint canvasPaint;
    private Canvas drawCanvas;
    private Bitmap canvasBitmap;
    private ArrayList<Path> paths = new ArrayList<Path>();
    private ArrayList<Path> undonePaths = new ArrayList<Path>();
    private ArrayList<float[]> PointsCal = new ArrayList<float[]>();
    private ArrayList<float[]> Points = new ArrayList<float[]>();
    private ArrayList<Integer> id = new ArrayList<Integer>();
    private int counter;
    public static WebSocket ws;
    private OkHttpClient client;
    Context myContext;
    Stroke drawnStroke;
    private List<Stroke> allStrokes;

public DrawingView(Context context, AttributeSet attr) {
    super(context, attr);
    setupDrawing();
    myContext = context;
}

private void setupDrawing() {
    allStrokes = new ArrayList<Stroke>();
    drawnStroke = new Stroke();

    canvasPaint = new Paint(Paint.DITHER_FLAG);
    drawCanvas = new Canvas();
    drawnStroke.paint.setAntiAlias(true);

    drawnStroke.paint.setStyle(Paint.Style.STROKE);
    drawnStroke.paint.setStrokeJoin(Paint.Join.ROUND);
    drawnStroke.paint.setStrokeCap(Paint.Cap.ROUND);
    counter = 0;
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    drawCanvas = new Canvas(canvasBitmap);
}

@Override
protected void onDraw(Canvas canvas) {

    if (allStrokes != null) {
        for (Stroke stroke : allStrokes) {
            if (stroke != null) {
                Path myPath = stroke.getPath();
                Paint myPaint = stroke.getPaint();

                myPaint.setAntiAlias(true);
                myPaint.setStyle(Paint.Style.STROKE);

                //this function below is not rendering in real time
                canvas.drawPath(myPath, myPaint);

            }
        }
    }
}

private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;

private void touch_start(float x, float y) {
    drawnStroke.getPaint().setColor(UserSettings.color);
    drawnStroke.getPaint().setStrokeWidth(UserSettings.width);
    drawnStroke.getPath().moveTo(x, y);
    mX = x;
    mY = y;
}


private void touch_move(float x, float y) {
    float dx = Math.abs(x - mX);
    float dy = Math.abs(y - mY);
    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
        drawnStroke.path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
        mX = x;
        mY = y;
    }
}


private void touch_up() {
    drawnStroke.path.lineTo(mX, mY);
    drawCanvas.drawPath(drawnStroke.path, drawnStroke.paint);
    allStrokes.add(drawnStroke);
    drawnStroke = new Stroke();
}


@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();
    float coordinates[] = {0f, 0f};
    float coord[] = {0f, 0f};
    String eventString;

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            touch_start(x, y);
            coordinates[0] = x;
            coordinates[1] = y;
            PointsCal.add(coordinates);
            Points.add(coordinates);
            invalidate();
            break;

        case MotionEvent.ACTION_MOVE:
            touch_move(x, y);
            coordinates[0] = x;
            coordinates[1] = y;
            PointsCal.add(coordinates);
            coord[0] = coordinates[0] - PointsCal.get(PointsCal.size() - 2)[0];
            coord[1] = coordinates[1] - PointsCal.get(PointsCal.size() - 2)[1];
            Points.add(coord);
            break;

        case MotionEvent.ACTION_UP:
            touch_up();
            coordinates[0] = x;
            coordinates[1] = y;
            PointsCal.add(coordinates);
            coord[0] = coordinates[0] - PointsCal.get(PointsCal.size() - 2)[0];
            coord[1] = coordinates[1] - PointsCal.get(PointsCal.size() - 2)[1];
            Points.add(coord);
            String sample = "";
            if (Points.size() > 2) {
                counter++;
                id.add(counter);
                sample += ("#" + counter);
                for (int i = 0; i < Points.size(); i++) {
                    sample += ("#" + Arrays.toString(Points.get(i)));
                }
            } else {
                paths.remove(paths.size() - 1);
            }
            Points.clear();
            PointsCal.clear();
            invalidate();
            break;
    }
    return true;
}

Upvotes: 0

Views: 599

Answers (1)

stkent
stkent

Reputation: 20128

I believe this is because allStrokes.add(drawnStroke); is not called until the private method touch_up is called, so when iterating over allStrokes for drawing purposes, the current stroke is omitted. Try moving that line of code to touch_start.

Upvotes: 1

Related Questions