最近在做android 涂鸦,采用的是在 FramLayout布局,后面一层加载的是背景图片,前面一层是自定义的view
public class PicEditView extends View { private int screenWidth, screenHeight;// 屏幕長寬 private Bitmap mBitmap; private Canvas mCanvas; private Path mPath; private Paint mBitmapPaint;// 画布的画笔 private Paint mPaint;// 真实的画笔 private float mX, mY;// 临时点坐标 private static final float TOUCH_TOLERANCE = 4; public PicEditView(Context context, int w, int h) { this(context, null); screenWidth = w; screenHeight = h; mBitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); mBitmapPaint = new Paint(Paint.DITHER_FLAG); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND);// 设置外边缘 mPaint.setStrokeCap(Paint.Cap.SQUARE);// 形状 mPaint.setStrokeWidth(5);// 画笔宽度 } public void setPaintColor(int color){ mPaint.setColor(color); } @Override protected void onAttachedToWindow() { // TODO Auto-generated method stub super.onAttachedToWindow(); } public PicEditView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { canvas.drawColor(0x00000000); // 将前面已经画过得显示出来 canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); if (mPath != null) { // 实时的显示 canvas.drawPath(mPath, mPaint); } super.onDraw(canvas); } private void touch_start(float x, float y) { mPath.moveTo(x, y); mX = x; mY = y; } private void touch_move(float x, float y) { float dx = Math.abs(x - mX); float dy = Math.abs(mY - y); //触摸间隔大于阈值才绘制路径 if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { // 从x1,y1到x2,y2画一条贝塞尔曲线,更平滑(直接用mPath.lineTo也是可以的) mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2); mX = x; mY = y; } } private void touch_up() { mPath.lineTo(mX, mY); mCanvas.drawPath(mPath, mPaint); } public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 每次down下去重新new一个Path mPath = new Path(); touch_start(x, y); System.out.println("ACTION_DOWN"); this.postInvalidate(); // invalidate(); break; case MotionEvent.ACTION_MOVE: System.out.println("--MOVE--"); touch_move(x, y); this.postInvalidate(); // invalidate(); break; case MotionEvent.ACTION_UP: touch_up(); System.out.println("--ACTION_UP--"); this.postInvalidate(); // invalidate(); break; } return true; } }
因此在加载图片是,缩小了图片的大小,从而可以流畅的涂鸦。
try { BitmapFactory.Options options = new BitmapFactory.Options(); //图片宽高都为原来的二分之一,即图片为原来的四分之一 //这样可以避免内存消耗,否则,后面绘图时,会出现很大的延时 options.inSampleSize = 2;// bitmap = BitmapFactory.decodeStream(getContentResolver() .openInputStream(imageFileUri),null,options); imgView.setImageBitmap(bitmap); // bitmap.recycle(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); }
layout = (FrameLayout) findViewById(R.id.container); DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); mView = new MView(this, displayMetrics.widthPixels, displayMetrics.heightPixels - dip2px(this, 40)); layout.addView(mView); findViewById(R.id.tSave).setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub layout.setDrawingCacheEnabled(true); layout.buildDrawingCache(); Bitmap b1 = layout.getDrawingCache(); //copy 缓存图像 Bitmap b = Bitmap.createBitmap(b1); layout.destroyDrawingCache();//这个之后,b1 就被 recycle了 System.out.println(Environment.getExternalStorageDirectory().getPath() ); File file = new File(Environment.getExternalStorageDirectory().getPath() +"/test1.png"); savePic(b, file); } });