title: How to draw path with variable width in canvas
body: <p>I am using the following line of code to draw a path on a Canvas. So far everything works fine and I can easily draw path using this code.</p>
  <p>But now our requirement is to draw a path with variable width, means the path user draw is based on the pressure applied by the user, I mean to say if the user applied light pressure the path will be thin and if the user applied high pressure the path will be thick and so on. So far I succeeded in drawing a path with variable width also, but the line drawn is not smooth. Why it is happening? Is anything I miss in my code?</p>
  <p>Help me to sort this out.</p>
  <p><strong>Code that I used for Drawing path with one Width</strong></p>
  <pre><code> 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&lt;Path&gt; mPaths = new ArrayList&lt;Path&gt;();
          
          ArrayList&lt;Integer&gt; mStrokes = new ArrayList&lt;Integer&gt;();
  
          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&lt;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()&gt;=0.00 &amp;&amp; event.getPressure()&lt;0.05)
                      {
                          variableWidthDelta = -2;
                      }
                      else if (event.getPressure()&gt;=0.05 &amp;&amp; event.getPressure()&lt;0.10)
                      {
                          variableWidthDelta = -2;
                      }
                      else if (event.getPressure()&gt;=0.10 &amp;&amp; event.getPressure()&lt;0.15)
                      {
                          variableWidthDelta = -2;
                      }
                      else if (event.getPressure()&gt;=0.15 &amp;&amp; event.getPressure()&lt;0.20)
                      {
                          variableWidthDelta = -2;
                      }
                      else if (event.getPressure()&gt;=0.20 &amp;&amp; event.getPressure()&lt;0.25)
                      {
                          variableWidthDelta = -2;
                      }
                      else if (event.getPressure() &gt;= 0.25 &amp;&amp; event.getPressure()&lt;0.30)
                      {
                          variableWidthDelta = 1;
                      }
                      else if (event.getPressure() &gt;= 0.30 &amp;&amp; event.getPressure()&lt;0.35)
                      {
                          variableWidthDelta = 2;
                      }
                      else if (event.getPressure() &gt;= 0.35 &amp;&amp; event.getPressure()&lt;0.40)
                      {
                          variableWidthDelta = 3;
                      }
                      else if (event.getPressure() &gt;= 0.40 &amp;&amp; event.getPressure()&lt;0.45)
                      {
                          variableWidthDelta = 4;
                      }
                      else if (event.getPressure() &gt;= 0.45 &amp;&amp; event.getPressure()&lt;0.60)
                      {
                          variableWidthDelta = 5;
                      }
                      
                      float dx = Math.abs(eventX - mX);
                      float dy = Math.abs(eventY - mY);
  
                      if (dx &gt;= TOUCH_TOLERANCE || dy &gt;= 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 &lt; 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 &lt; 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 &lt; dirtyRect.left)
              {
                  dirtyRect.left = historicalX;
              } 
              else if (historicalX &gt; dirtyRect.right)
              {
                  dirtyRect.right = historicalX;
              }
              if (historicalY &lt; dirtyRect.top) 
              {
                  dirtyRect.top = historicalY;
              } 
              else if (historicalY &gt; 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);
          }
      }
  }
  </code></pre>
  <p><img src="https://i.stack.imgur.com/pMPZ7.png" alt="enter image description here" /></p>