canvas教程

画布上涂鸦功能(可橡皮擦、可清除)

字号+ 作者:H5之家 来源:H5之家 2017-01-01 17:07 我要评论( )

package com.yjkj.sandihuabing.view.widget;import android.content.Context;import android.content.Intent;import android.graphics.Bitmap;import android.g

package com.yjkj.sandihuabing.view.widget; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.net.Uri; import android.os.Environment; import android.util.Log; import android.view.MotionEvent; import android.view.View; import com.yjkj.sandihuabing.model.Coord; import com.yjkj.sandihuabing.util.Util; import java.io.File; import java.io.FileOutputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; /** * Created by yunjia on 2016/11/4. */ public class TuyaView extends View{ private Context context; 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; // 保存Path路径的集合 private static List<DrawPath> savePath; // 保存已删除Path路径的集合 private static List<DrawPath> deletePath; // 记录Path路径的坐标点 private List<Coord> coordList; private List<List<Coord>> list; private List<Coord> coords; private DrawPath dp; private int screenWidth, screenHeight; private int currentColor = Color.BLACK; private int currentSize = 10; private class DrawPath { public Path path;// 路径 public Paint paint;// 画笔 } public TuyaView(Context context, int w, int h) { super(context); this.context = context; screenWidth = w; screenHeight = h; setLayerType(LAYER_TYPE_SOFTWARE,null);//设置默认样式,去除dis-in的黑色方框以及clear模式的黑线效果 initCanvas(); savePath = new ArrayList<DrawPath>(); deletePath = new ArrayList<DrawPath>(); coordList = new ArrayList<>(); coords = new ArrayList<>(); list = new ArrayList<>(); } public void initCanvas() { setPaintStyle(); mBitmapPaint = new Paint(Paint.DITHER_FLAG); //画布大小 mBitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888); mBitmap.eraseColor(Color.argb(0, 0, 0, 0)); mCanvas = new Canvas(mBitmap); //所有mCanvas画的东西都被保存在了mBitmap中 mCanvas.drawColor(Color.TRANSPARENT); } //初始化画笔样式 private void setPaintStyle() { mPaint = new Paint(); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND);// 设置外边缘 mPaint.setStrokeCap(Paint.Cap.ROUND);// 形状 mPaint.setAntiAlias(true); mPaint.setDither(true); } @Override public void onDraw(Canvas canvas) { //canvas.drawColor(0xFFAAAAAA); // 将前面已经画过得显示出来 canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); if (mPath != null) { // 实时的显示 canvas.drawPath(mPath, mPaint); } } 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); //mPath.lineTo(mX,mY); mX = x; mY = y; if(mPaint.getColor() == Color.BLACK && mPaint.getStrokeWidth() == currentSize){ // coords.add(new Coord(Util.format(x/screenWidth),Util.format(y/screenHeight))); coordList.add(new Coord(Util.format(x/screenWidth),Util.format(y/screenHeight))); } if(mPaint.getColor() == Color.TRANSPARENT && mPaint.getStrokeWidth() == 80){ coords.add(new Coord(Util.format(x/screenWidth),Util.format(y/screenHeight))); } } } private void touch_up() { mPath.lineTo(mX, mY); mCanvas.drawPath(mPath, mPaint); //将一条完整的路径保存下来 savePath.add(dp); mPath = null;// 重新置空 if(coordList.size() > 0){ list.add(coordList); coordList = new ArrayList<>(); } // if(coords.size() > 0 && list.size() > 0){ // for(int i = 0;i < list.size();i++){ // List<Coord> list1 = list.get(i); // for(int j= 0; j < list1.size();j++){ // for(int q = 0;q < coords.size();q++){ // if(list1.contains(coords.get(q))){ // list1.remove(j); // q--; // } // } // // // } // } // coords = new ArrayList<>(); // } } /** * 画图 */ public void brush(){ setPaintStyle(); mPaint.setColor(currentColor); mPaint.setStrokeWidth(currentSize); } /** * 橡皮 */ public void eraser(){ setPaintStyle(); mPaint.setAlpha(0); mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); mPaint.setColor(Color.TRANSPARENT); mPaint.setStrokeWidth(80); } /** * 撤销 * 撤销的核心思想就是将画布清空, * 将保存下来的Path路径最后一个移除掉, * 重新将路径画在画布上面。 */ public void undo() { if (savePath != null && savePath.size() > 0) { DrawPath drawPath = savePath.get(savePath.size() - 1); deletePath.add(drawPath); savePath.remove(savePath.size() - 1); redrawOnBitmap(); } } /** * 重做 */ public void redo() { if (savePath != null && savePath.size() > 0) { savePath.clear(); redrawOnBitmap(); } list.clear(); coords.clear(); coordList.clear(); } private void redrawOnBitmap() { /*mBitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.RGB_565); mCanvas.setBitmap(mBitmap);// 重新设置画布,相当于清空画布*/ initCanvas(); Iterator<DrawPath> iter = savePath.iterator(); while (iter.hasNext()) { DrawPath drawPath = iter.next(); mCanvas.drawPath(drawPath.path, drawPath.paint); } invalidate();// 刷新 } /** * 恢复,恢复的核心就是将删除的那条路径重新添加到savapath中重新绘画即可 */ public void recover() { if (deletePath.size() > 0) { //将删除的路径列表中的最后一个,也就是最顶端路径取出(栈),并加入路径保存列表中 DrawPath dp = deletePath.get(deletePath.size() - 1); savePath.add(dp); //将取出的路径重绘在画布上 mCanvas.drawPath(dp.path, dp.paint); //将该路径从删除的路径列表中去除 deletePath.remove(deletePath.size() - 1); invalidate(); } } @Override 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(); //每一次记录的路径对象是不一样的 dp = new DrawPath(); dp.path = mPath; dp.paint = mPaint; touch_start(x, y); invalidate(); break; case MotionEvent.ACTION_MOVE: touch_move(x, y); invalidate(); break; case MotionEvent.ACTION_UP: touch_up(); invalidate(); break; } return true; } //保存到sd卡 public void saveToSDCard() { //获得系统当前时间,并以该时间作为文件名 SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss"); Date curDate = new Date(System.currentTimeMillis());//获取当前时间 String str = formatter.format(curDate) + "paint.png"; File file = new File("sdcard/" + str); FileOutputStream fos = null; try { fos = new FileOutputStream(file); } catch (Exception e) { e.printStackTrace(); } mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); //发送Sd卡的就绪广播,要不然在手机图库中不存在 Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED); intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory())); context.sendBroadcast(intent); Log.e("TAG", "图片已保存"); } //选择画笔大小 public void selectPaintSize(int which) { //int size = Integer.parseInt(this.getResources().getStringArray(R.array.paintsize)[which]); currentSize = which; setPaintStyle(); } public Bitmap getmBitmap(){ return mBitmap; } public List<DrawPath> getSavePath(){ return savePath; } public List<Coord> getCoordList(){ return coordList; } public List<List<Coord>> getList(){ return list; } }

 

爱编程-编程爱好者经验分享平台

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
网友点评