绘制的补充: @Override protected void onDraw(Canvas canvas) { Rect r = canvas.getClipBounds(); PathInfo pathInfo; for (int i = 0; i < mPathInfo.size(); i++){ pathInfo = mPathInfo.get(i); if (Rect.intersects(r, pathInfo.rect)){ mPaint.setColor(pathInfo.color); //press mPaint.setStrokeWidth(pathInfo.press); //press over } canvas.drawPath(pathInfo.path, mPaint); } mPaint.setColor(GlobalSetting.mScriptColor); canvas.drawPath(mPath, mPaint); } onTouchEvent处理: private final float PRESS_OFFSET = 2.5f; @Override public boolean onTouchEvent(MotionEvent event) { if ( action == MotionEvent.ACTION_DOWN ) { mCurX = (int)event.getX(); mCurY = (int)event.getY(); mPrevX = mCurX; mPrevY = mCurY; //press float pressD = event.getPressure(); float width = getEventPress(pressD); mPaint.setStrokeWidth(width); mPath = new Path(); mPath.moveTo(mCurX, mCurY); mPath.computeBounds(mRectF, true); mRect.set(((int)mRectF.left - (int)width), ((int)mRectF.top - (int)width), ((int)mRectF.right + (int)width), ((int)mRectF.bottom + (int)width)); PathInfo pathInfoH = new PathInfo(mPath, mRect, width); mPathInfo.add(pathInfoH); mPrePress = width; invalidate(mRect); return true; } //moving int N = event.getHistorySize(); Log.i(TAG,"N:"+N); int x = 0; int y = 0; float pressH = 0; int i=0; for (i=0; i<N; i++) { x = (int)event.getHistoricalX(i); y = (int)event.getHistoricalY(i); //press pressH =event.getHistoricalPressure(i); float width = getEventPress(pressH); mPath = new Path(); mPaint.setStrokeWidth(width-i); drawPoint(mCurX, mCurY, x, y); mPath.computeBounds(mRectF, true); mRect.set(((int)mRectF.left - (int)width-i), ((int)mRectF.top - (int)width-i), ((int)mRectF.right + (int)width-i), ((int)mRectF.bottom + (int)width-i)); PathInfo pathInfoH = new PathInfo(mPath, mRect, width); mPathInfo.add(pathInfoH); mCurX = x; mCurY = y; StrokeMgr.instance().addStroke((short)mCurX, (short)mCurY); mPrePress = width; invalidate(mRect); } x = (int)event.getX(); y = (int)event.getY(); //press pressH = event.getPressure(); float width = getEventPress(pressH); if( width > mPrePress +PRESS_OFFSET ){ width = mPrePress+PRESS_OFFSET; }else if(width < mPrePress - PRESS_OFFSET){ width = mPrePress-PRESS_OFFSET; } mPrePress = width; mPath = new Path(); drawPoint(mCurX, mCurY, x, y); mPaint.setStrokeWidth(width-i); mPath.computeBounds(mRectF, true); mRect.set(((int)mRectF.left - (int)width), ((int)mRectF.top - (int)width), ((int)mRectF.right + (int)width), ((int)mRectF.bottom + (int)width)); PathInfo pathInfoM = new PathInfo(mPath, mRect, width); mPathInfo.add(pathInfoM); //press over mCurX = x; mCurY = y; StrokeMgr.instance().addStroke((short)mCurX, (short)mCurY); if ( action == MotionEvent.ACTION_UP ){ mPath.computeBounds(mRectF, true); float widthUp = getEventPress(event.getPressure()); if( widthUp > mPrePress +PRESS_OFFSET ){ widthUp = mPrePress+PRESS_OFFSET; }else if(widthUp < mPrePress - PRESS_OFFSET){ widthUp = mPrePress-PRESS_OFFSET; } mRect.set( (int)(mRectF.left - widthUp), (int)(mRectF.top - widthUp), (int)(mRectF.right + widthUp), (int)(mRectF.bottom + widthUp) ); mPrePress = widthUp; PathInfo pathInfoUp = new PathInfo(mPath, mRect, widthUp); mPathInfo.add(pathInfoUp); // fadePoints(); mCurX = -1; mCurY = 0; } invalidate(mRect); return true; } 如果需要填充渐变: private int[] mFadeColor = { 0xffffffff, 0xddffffff, 0xaaffffff, 0x99ffffff, 0x77ffffff, 0x66ffffff, 0x55ffffff, 0x44ffffff, 0x39ffffff, 0x33ffffff, 0x22ffffff, 0x17ffffff, 0x11ffffff, 0x09ffffff, 0x05ffffff, 0x00ffffff}; private void fadePoints(){ int count = mPathInfo.size(); int start = count - 1; int end = count - 16; end = end < 0 ? 0 : end; PathInfo pathInfo; int index = 0; for (int i = start; i >= end; i--, index++){ pathInfo = mPathInfo.get(i); pathInfo.color = ( pathInfo.color | 0xff000000 ) & mFadeColor[index]; mRect.union(pathInfo.rect); } }