我创建了一个示例绘图应用程序,用户可以在其中使用宽度可变的笔画进行绘制。到目前为止,具有可变笔划的绘制路径都可以使用,但是绘制的线条并不平滑。我用来实现的代码如下所示。
过去两天来,我一直无法解决这个问题,请帮我解决。
使用可变笔触宽度绘制路径的代码
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(); ArrayListmPaths = new ArrayList (); ArrayList mStrokes = new ArrayList (); private float lastTouchX; private float lastTouchY; private final RectF dirtyRect = new RectF(); private int lastStroke = -1; int variableWidthDelta = 0; private static final float STROKE_DELTA = 0.0001f; // for float comparison private static final float STROKE_INCREMENT = 0.01f; // amount to interpolate private float currentStroke = STROKE_WIDTH; private float targetStroke = STROKE_WIDTH; 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 =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; } // if current not roughly equal to target if( Math.abs(targetStroke - currentStroke) > STROKE_DELTA ) { // move towards target by the increment if( targetStroke > currentStroke) { currentStroke = Math.min(targetStroke, currentStroke + STROKE_INCREMENT); } else { currentStroke = Math.max(targetStroke, currentStroke - STROKE_INCREMENT); } } mStrokes.add((int) currentStroke); targetStroke = variableWidthDelta; 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); } 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); } } }
我得到的输出结果
我想要实现的输出