自定义一个写字板来帮助理解双缓存。如果不使用双缓存那么用户只能看到绘制的最后一笔的效果。因为在不断调用invalidate(),未保存的绘制过程会消失。
package newviews; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; /** * Created by yuanteng on 2017/9/11. */ public class DrawNsmeView extends View {; private Paint paint; private Path path; //绘图是用于缓存绘制过程的bitmap private Bitmap bufferBitmap; private Canvas bufferCanvas; private int preX,preY; public DrawNsmeView(Context context, AttributeSet attrs) { super(context, attrs); path = new Path(); paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.RED); paint.setStrokeWidth(5); paint.setStyle(Paint.Style.STROKE); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); int width = getMeasuredWidth(); int height = getMeasuredHeight(); bufferBitmap = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888); if (bufferCanvas == null){ bufferCanvas = new Canvas(bufferBitmap); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawBitmap(bufferBitmap,0,0,null); // canvas.drawPath(path,paint); } @Override public boolean onTouchEvent(MotionEvent event) { int x = (int)event.getX(); int y = (int)event.getY(); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: //重置path 清除path中保存的数据 path.reset(); preX = x; preY = y; //将起点移动到此处 path.moveTo(x,y); break; case MotionEvent.ACTION_MOVE: //画贝塞尔曲线,贝塞尔曲线比bufferCanvas.drawLine();画出来的曲线更平滑 path.quadTo(preX,preY,x,y); //通知重绘制view bufferCanvas.drawPath(path,paint); invalidate(); preY = y; preX = x; break; case MotionEvent.ACTION_UP: //抬起时将path绘制在buffer中保存,并崇绘制view,崇绘制的时候回绘制buffer bufferCanvas.drawPath(path,paint); invalidate(); break; } return true; } }
效果图:用模拟器画的效果没有真机好