Search code examples
androidandroid-canvasandroid-viewandroid-gesture

Android canvas - Drawing arc between to points and removing arc from path


In my android application, i want to provide tracing letter feature as shown in following image :

enter image description here

Here i want to provide tracing of letter-D and for that i need to draw arc between two points when user starts moving finger on arc. Here, if user starts moving finger from start point and stops at end point then only it should draw arc between those points. And it should also show arc while moving finger on arc path.For that i have written below code.The problem i am facing is that, when ACTION_UP event is fired on arc path, it still shows arc drawing on canvas. But i want to remove that drawing from path if it fires ACTION_UP event in between of arc path.

Here is my code :

public class DrawView extends View implements OnTouchListener {

List<Point> pointsD = new ArrayList<Point>();
pointsD.add(new Point(520, 70));
    pointsD.add(new Point(520, 335));
    pointsD.add(new Point(520, 70));
    pointsD.add(new Point(520, 335));

public boolean onTouch(View view, MotionEvent event) {

    float x = event.getX();
    float y = event.getY();

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        touch_start(x, y);
        invalidate();
        break;
    case MotionEvent.ACTION_MOVE:
        touch_move(x, y);
        invalidate();
        break;
    case MotionEvent.ACTION_UP:
        touch_up(x, y);
        invalidate();
        break;
    default:
        break;
    }
    return true;
}
private void touch_start(float x, float y) {
      if (checkPoint(x, y, mLastPointIndex)) {
                mPath.reset();
            isPathStarted = true;
          } else {
            isPathStarted = false;
      }
}

private void touch_move(float x, float y) {

    if (isPathStarted) {
        mPath.reset();
        Point p = null;
         p = pointsD.get(mLastPointIndex);
        mPath.moveTo(p.x, p.y);
            float radius = 1;
        RectF oval = new RectF();
        oval.set(scalePointX((int) (486 - radius)),scalePointY(70),                               scalePointX((int) (686 + radius)),
                        scalePointY((int) (334 + radius)));
        if (sweepAngelD <= 180 && startAngleD <= 360) {
            mPath.arcTo(oval, startAngleD, sweepAngelD, true);
        sweepAngelD += 1;
        startAngleD += 2;
        mCanvas.drawPath(mPath, mPaint);
    }
    mPath.reset();
}

private void touch_up(float x, float y) {
       mPath.reset();
            if (isPathStarted) {
                float radius = 1;
                RectF oval = new RectF();
                oval.set(scalePointX((int) (486 - radius)),
                        scalePointY(70), scalePointX((int) (686 + radius)),
                        scalePointY((int) (334 + radius)));
                Point p = pointsD.get(mLastPointIndex);
                mPath.moveTo(p.x, p.y);
                mPath.arcTo(oval, startAngleD, sweepAngelD, true);                  
                mCanvas.drawPath(mPath, mPaint);
                mPath.reset();
                ++mLastPointIndex;
            } else {
                sweepAngelD = 1;
                startAngleD = 270;
                mPath.reset();
             }
            isPathStarted = false;
 }

private boolean checkPoint(float x, float y, int pointIndex){
if (pointIndex == pointsD.size()) {
            // out of bounds
            return false;
        }
        point = pointsD.get(pointIndex);
        // EDIT changed point.y to poin.x in the first if statement
        if (x > (point.x - TOUCH_TOLERANCE)
                && x < (point.x + TOUCH_TOLERANCE)) {
            if (y > (point.y - TOUCH_TOLERANCE)
                    && y < (point.y + TOUCH_TOLERANCE)) {
                return true;
            }
        }
    return false;
}
}

Solution

  • I edited my code as below and now it is working..

        public class DrawView extends View implements OnTouchListener {
    
    List<Point> pointsD = new ArrayList<Point>();
    pointsD.add(new Point(520, 70));
        pointsD.add(new Point(520, 335));
        pointsD.add(new Point(520, 70));
        pointsD.add(new Point(520, 335));
    
    public boolean onTouch(View view, MotionEvent event) {
    
        float x = event.getX();
        float y = event.getY();
    
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            touch_start(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            touch_move(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            touch_up(x, y);
            invalidate();
            break;
        default:
            break;
        }
        return true;
    }
    private void touch_start(float x, float y) {
          if (checkPoint(x, y, mLastPointIndex)) {
                    mPath.reset();
                isPathStarted = true;
              } else {
                isPathStarted = false;
          }
    }
    
    private void touch_move(float x, float y) {
    
        if (isPathStarted) {
            mPath.reset();
            Point p = null;
             p = pointsD.get(mLastPointIndex);
            mPath.moveTo(p.x, p.y);
                float radius = 1;
            RectF oval = new RectF();
            oval.set(scalePointX((int) (486 - radius)),scalePointY(70),                               scalePointX((int) (686 + radius)),
                            scalePointY((int) (334 + radius)));
            if (sweepAngelD <= 180 && startAngleD <= 360) {
                mPath.arcTo(oval, startAngleD, sweepAngelD, true);
            sweepAngelD += 1;
            startAngleD += 2;
    
        }
        mPath.reset();
    }
    
    private void touch_up(float x, float y) {
           mPath.reset();
                if (isPathStarted) {
                    float radius = 1;
                    RectF oval = new RectF();
                    oval.set(scalePointX((int) (486 - radius)),
                            scalePointY(70), scalePointX((int) (686 + radius)),
                            scalePointY((int) (334 + radius)));
                    Point p = pointsD.get(mLastPointIndex);
                    mPath.moveTo(p.x, p.y);
                    mPath.arcTo(oval, startAngleD, sweepAngelD, true);                  
                    mCanvas.drawPath(mPath, mPaint);
                    mPath.reset();
                    ++mLastPointIndex;
                } else {
                    sweepAngelD = 1;
                    startAngleD = 270;
                    mPath.reset();
                 }
                isPathStarted = false;
     }
    
    private boolean checkPoint(float x, float y, int pointIndex){
    if (pointIndex == pointsD.size()) {
                // out of bounds
                return false;
            }
            point = pointsD.get(pointIndex);
            // EDIT changed point.y to poin.x in the first if statement
            if (x > (point.x - TOUCH_TOLERANCE)
                    && x < (point.x + TOUCH_TOLERANCE)) {
                if (y > (point.y - TOUCH_TOLERANCE)
                        && y < (point.y + TOUCH_TOLERANCE)) {
                    return true;
                }
            }
        return false;
    }
    }