How to draw a variable width path in canvas

I use the following line of code to draw a path on the Canvas, so far everything is working fine, and I can easily draw the path using this code.

But now our requirement is to draw a path with a variable width, means that the user’s drawing of the path is based on the pressure applied by the user, I mean, if the user applies light pressure, the path will be thin, and if the user is applied at high the pressure path will be thick and so on. So far, I have also managed to draw a variable-width path, but the drawn line was not smooth. Why this is happening is what I missed in my code.

Help me cut it.

The code I used for the single-width drawing path

 public class FingerPaint extends GraphicsActivity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));
    }

    public void colorChanged(int color) 
    {

    }

    public class MyView extends View 
    {
        private static final float STROKE_WIDTH = 5f;       

        private Paint paint = new Paint();

        private Path mPath = new Path();
        ArrayList<Path> mPaths = new ArrayList<Path>();

        ArrayList<Integer> mStrokes = new ArrayList<Integer>();

        private float lastTouchX;
        private float lastTouchY;
        private final RectF dirtyRect = new RectF();

        private int lastStroke = -1;
        int variableWidthDelta = 0;

        private float           mX, mY;

        private static final float       TOUCH_TOLERANCE = 4;

        public MyView(Context context) 
        {
            super(context);

            paint.setAntiAlias(true);
            paint.setDither(true);
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeJoin(Paint.Join.ROUND);
            paint.setStrokeCap(Paint.Cap.ROUND);    
            paint.setStrokeWidth(STROKE_WIDTH);
        }

        public void clear()
        {
            mPath.reset();
            // Repaints the entire view.
            invalidate();
        }

        @Override
        protected void onDraw(Canvas canvas) 
        {
            for(int i=0; i<mPaths.size();i++)
            {
                paint.setStrokeWidth(mStrokes.get(i));
                canvas.drawPath(mPaths.get(i), paint);
            }
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) 
        {
            float eventX = event.getX();
            float eventY = event.getY();
            int historySize = event.getHistorySize();

            switch (event.getAction()) 
            {
                case MotionEvent.ACTION_DOWN:
                {
                    resetDirtyRect(eventX, eventY);
                    mPath.reset();
                    mPath.moveTo(eventX, eventY);
                    mX = eventX;
                    mY = eventY;
                    break;                  
                }
                case MotionEvent.ACTION_MOVE:
                {                   
                    if (event.getPressure()>=0.00 && event.getPressure()<0.05)
                    {
                        variableWidthDelta = -2;
                    }
                    else if (event.getPressure()>=0.05 && event.getPressure()<0.10)
                    {
                        variableWidthDelta = -2;
                    }
                    else if (event.getPressure()>=0.10 && event.getPressure()<0.15)
                    {
                        variableWidthDelta = -2;
                    }
                    else if (event.getPressure()>=0.15 && event.getPressure()<0.20)
                    {
                        variableWidthDelta = -2;
                    }
                    else if (event.getPressure()>=0.20 && event.getPressure()<0.25)
                    {
                        variableWidthDelta = -2;
                    }
                    else if (event.getPressure() >= 0.25 && event.getPressure()<0.30)
                    {
                        variableWidthDelta = 1;
                    }
                    else if (event.getPressure() >= 0.30 && event.getPressure()<0.35)
                    {
                        variableWidthDelta = 2;
                    }
                    else if (event.getPressure() >= 0.35 && event.getPressure()<0.40)
                    {
                        variableWidthDelta = 3;
                    }
                    else if (event.getPressure() >= 0.40 && event.getPressure()<0.45)
                    {
                        variableWidthDelta = 4;
                    }
                    else if (event.getPressure() >= 0.45 && event.getPressure()<0.60)
                    {
                        variableWidthDelta = 5;
                    }

                    float dx = Math.abs(eventX - mX);
                    float dy = Math.abs(eventY - mY);

                    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
                    {
                        if(lastStroke != variableWidthDelta)
                        {   
                            mPath.lineTo(mX, mY);

                            mPath = new Path();
                            mPath.moveTo(mX,mY);
                            mPaths.add(mPath);
                            mStrokes.add(variableWidthDelta);
                        }

                        mPath.quadTo(mX, mY, (eventX + mX)/2, (eventY + mY)/2);
                        mX = eventX;
                        mY = eventY;
                    }

                    for (int i = 0; i < historySize; i++)
                    {
                        float historicalX = event.getHistoricalX(i);
                        float historicalY = event.getHistoricalY(i);
                        expandDirtyRect(historicalX, historicalY);
                    }

                    break;
                }
                case MotionEvent.ACTION_UP:
                {
                    for (int i = 0; i < historySize; i++)
                    {
                        float historicalX = event.getHistoricalX(i);
                        float historicalY = event.getHistoricalY(i);
                        expandDirtyRect(historicalX, historicalY);
                    }

                   mPath.lineTo(mX, mY);                   
                   break;
                }
            }

            // Include half the stroke width to avoid clipping.
            invalidate();

            lastTouchX = eventX;
            lastTouchY = eventY;
            lastStroke = variableWidthDelta;

            return true;
        }

        private void expandDirtyRect(float historicalX, float historicalY) 
        {
            if (historicalX < dirtyRect.left)
            {
                dirtyRect.left = historicalX;
            } 
            else if (historicalX > dirtyRect.right)
            {
                dirtyRect.right = historicalX;
            }
            if (historicalY < dirtyRect.top) 
            {
                dirtyRect.top = historicalY;
            } 
            else if (historicalY > dirtyRect.bottom) 
            {
                dirtyRect.bottom = historicalY;
            }
        }

        /**
         * Resets the dirty region when the motion event occurs.
         */
        private void resetDirtyRect(float eventX, float eventY) 
        {
            // The lastTouchX and lastTouchY were set when the ACTION_DOWN
            // motion event occurred.
            dirtyRect.left = Math.min(lastTouchX, eventX);
            dirtyRect.right = Math.max(lastTouchX, eventX);
            dirtyRect.top = Math.min(lastTouchY, eventY);
            dirtyRect.bottom = Math.max(lastTouchY, eventY);
        }
    }
}

enter image description here

+1
6

.

, MotionEvent.getPressure() VelocityTracker.computeCurrentVelocity().

.

, , . , 10 50 , 10 5,10,15,20... . , Path .

quad-curve .

0
@Override
    protected synchronized void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        this.canvas = canvas;
        Log.d("tag", "Padding" + padding);
        int newPadding = (int) padding;

        // Set Min X
        int xPadding = (int) padding;
        Paint bottomLeftTextPaint = new Paint();
        Typeface tf = Typeface.create("Helvetica", Typeface.NORMAL);
        bottomLeftTextPaint.setColor(context.getResources().getColor(
                R.color.common_color_rangeseekbar_bottomtext));
        bottomLeftTextPaint.setTextAlign(Align.LEFT);
        bottomLeftTextPaint.setTypeface(tf);
        bottomLeftTextPaint.setTextSize(20);

        bottomLeftTextPaint.setColor(context.getResources().getColor(
                R.color.common_color_rangeseekbar_bottomtext));
        canvas.drawText(absoluteMinValue + "", newPadding - 5,
                0.5f * (getHeight() + lineHeight) + 30, bottomLeftTextPaint);
        // draw seek bar background line
        final RectF rect = new RectF(newPadding - 5,
                0.5f * (getHeight() - lineHeight), getWidth() - padding,
                0.5f * (getHeight() + lineHeight));
        paint.setStyle(Style.FILL);
        // paint.setColor(Color.parseColor("#ED797F"));
        paint.setColor(Color.parseColor("#e2e2e2"));
        paint.setAntiAlias(true);
        canvas.drawRect(rect, paint);
        RectF rectStartLine = new RectF(newPadding - 5,
                0.5f * (getHeight() - lineHeight) - 5, padding,
                0.5f * (getHeight() + lineHeight) + 5);
        paint.setStyle(Style.FILL);
        paint.setColor(Color.BLACK);
        paint.setAntiAlias(true);
        canvas.drawRect(rectStartLine, paint);
        // End Line
        // RectF rectEndLine = new RectF(getWidth() - padding,
        // 0.5f * (getHeight() - lineHeight) - 5,
        // getWidth() - padding + 5, 0.5f * (getHeight() + lineHeight) + 5);
        RectF rectEndLine = new RectF(getWidth() - padding,
                0.5f * (getHeight() - lineHeight) - 5,
                getWidth() - padding + 5, 0.5f * (getHeight() + lineHeight) + 5);
        paint.setStyle(Style.FILL);
        paint.setColor(Color.BLACK);
        paint.setAntiAlias(true);
        canvas.drawRect(rectEndLine, paint);
        // End Text
        // Set Min X
        int xEndPadding = (int) padding;

        paint.setColor(Color.parseColor(context.getResources().getString(
                R.color.common_color_rangeseekbar_bottomtext)));
        paint.setTextSize(20);
        int max = (Integer) absoluteMaxValue;
        String MaxValue = String.valueOf(max);
        paint.setColor(Color.parseColor(context.getResources().getString(
                R.color.common_color_rangeseekbar_bottomtext)));
        Paint bottomTextPaint = new Paint();
        bottomTextPaint.setTypeface(tf);
        bottomTextPaint.setColor(context.getResources().getColor(
                R.color.common_color_rangeseekbar_bottomtext));
        bottomTextPaint.setTextAlign(Align.RIGHT);
        bottomTextPaint.setTypeface(tf);
        bottomTextPaint.setTextSize(20);
        // if (MaxValue.length() > 4) {
        //
        // canvas.drawText(absoluteMaxValue + "", getWidth() - padding - 23,
        // 0.5f * (getHeight() + lineHeight) + 30, bottomTextPaint);
        // } else if (MaxValue.length() > 3) {
        // canvas.drawText(absoluteMaxValue + "", getWidth() - padding - 18,
        // 0.5f * (getHeight() + lineHeight) + 30, bottomTextPaint);
        // } else if (MaxValue.length() > 2) {
        // canvas.drawText(absoluteMaxValue + "", getWidth() - padding - 13,
        // 0.5f * (getHeight() + lineHeight) + 30, bottomTextPaint);
        // } else {
        canvas.drawText(absoluteMaxValue + "", getWidth() - padding,
                0.5f * (getHeight() + lineHeight) + 30, bottomTextPaint);
        // }
        // draw seek bar active range line
        rect.left = normalizedToScreen(normalizedMinValue);
        rect.right = normalizedToScreen(normalizedMaxValue);

        // orange color
        paint.setColor(DEFAULT_COLOR);
        paint.setTypeface(tf);

        canvas.drawRect(rect, paint);
        Paint headerPaint = new Paint();
        // Set TextSize
        headerPaint.setTextSize(20);
        headerPaint.setTextAlign(Align.LEFT);
        headerPaint.setTypeface(tf);
        headerPaint.setColor(Color.parseColor(context.getResources().getString(
                R.color.common_color_rangeseekbar_toptext)));
        headerPaint.setTextAlign(Align.LEFT);
        // draw minimum thumb
        drawThumb(normalizedToScreen(normalizedMinValue),
                Thumb.MIN.equals(pressedThumb), canvas);
        canvas.drawText("" + getSelectedMinValue(),
                normalizedToScreen(normalizedMinValue)-5,
                (float) ((0.5f * getHeight()) - thumbHalfHeight) - 8,
                headerPaint);
        // draw maximum thumb
        drawThumb(normalizedToScreen(normalizedMaxValue),
                Thumb.MAX.equals(pressedThumb), canvas);
        // Right TrackText
        Paint righText = new Paint();
        righText.setTextAlign(Align.RIGHT);
        righText.setAntiAlias(true);
        righText.setTextSize(20);
        righText.setTypeface(tf);
        canvas.drawText("" + getSelectedMaxValue(),
                normalizedToScreen(normalizedMaxValue),
                (float) ((0.5f * getHeight()) - thumbHalfHeight) , righText);
    }
0

, , .

0

All Articles