diff --git a/src/main/java/net/micode/notes/PaintView.java b/src/main/java/net/micode/notes/PaintView.java new file mode 100644 index 0000000..12ca9b5 --- /dev/null +++ b/src/main/java/net/micode/notes/PaintView.java @@ -0,0 +1,271 @@ +package net.micode.notes; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; + +import android.app.Activity; +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.util.DisplayMetrics; +import android.view.MotionEvent; +import android.view.View; + +/** + * + * @category: View实现涂鸦、撤销以及重做功能 + * @author: dingruihua + * @date: 2022.10.10 + * + */ + +public class PaintView extends View { + + private Canvas mCanvas; + private Path mPath; + private Paint mBitmapPaint; + private Bitmap mBitmap; + private Paint mPaint; + + private ArrayList savePath; + private ArrayList deletePath; + private DrawPath dp; + + private float mX, mY; + private static final float TOUCH_TOLERANCE = 4; + + private int bitmapWidth; + private int bitmapHeight; + + public PaintView(Context c) { + super(c); + //得到屏幕的分辨率 + DisplayMetrics dm = new DisplayMetrics(); + ((Activity) c).getWindowManager().getDefaultDisplay().getMetrics(dm); + + bitmapWidth = dm.widthPixels; + bitmapHeight = dm.heightPixels - 2 * 45; + + initCanvas(); + savePath = new ArrayList(); + deletePath = new ArrayList(); + + } + public PaintView(Context c, AttributeSet attrs) { + super(c,attrs); + //得到屏幕的分辨率 + DisplayMetrics dm = new DisplayMetrics(); + ((Activity) c).getWindowManager().getDefaultDisplay().getMetrics(dm); + + bitmapWidth = dm.widthPixels; + bitmapHeight = dm.heightPixels - 2 * 45; + + initCanvas(); + savePath = new ArrayList(); + deletePath = new ArrayList(); + } + //初始化画布 + public void initCanvas(){ + + mPaint = new Paint(); + mPaint.setAntiAlias(true); + mPaint.setDither(true); + mPaint.setColor(0xFF00FF00); + mPaint.setStyle(Paint.Style.STROKE); + mPaint.setStrokeJoin(Paint.Join.ROUND); + mPaint.setStrokeCap(Paint.Cap.ROUND); + mPaint.setStrokeWidth(10); + + mBitmapPaint = new Paint(Paint.DITHER_FLAG); + + + + //画布大小 + mBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, + Bitmap.Config.RGB_565); + mCanvas = new Canvas(mBitmap); //所有mCanvas画的东西都被保存在了mBitmap中 + + mCanvas.drawColor(Color.WHITE); + mPath = new Path(); + mBitmapPaint = new Paint(Paint.DITHER_FLAG); + + } + + + @Override + protected void onDraw(Canvas canvas) { + + canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); //显示旧的画布 + if (mPath != null) { + // 实时的显示 + canvas.drawPath(mPath, mPaint); + } + } + //路径对象 + class DrawPath{ + Path path; + Paint paint; + } + + /** + * 撤销的核心思想就是将画布清空, + * 将保存下来的Path路径最后一个移除掉, + * 重新将路径画在画布上面。 + */ + public void undo(){ + + System.out.println(savePath.size()+"--------------"); + if(savePath != null && savePath.size() > 0){ + //调用初始化画布函数以清空画布 + initCanvas(); + + //将路径保存列表中的最后一个元素删除 ,并将其保存在路径删除列表中 + DrawPath drawPath = savePath.get(savePath.size() - 1); + deletePath.add(drawPath); + savePath.remove(savePath.size() - 1); + + //将路径保存列表中的路径重绘在画布上 + Iterator iter = savePath.iterator(); //重复保存 + while (iter.hasNext()) { + DrawPath dp = iter.next(); + mCanvas.drawPath(dp.path, dp.paint); + + } + invalidate();// 刷新 + } + } + /** + * 恢复的核心思想就是将撤销的路径保存到另外一个列表里面(栈), + * 然后从redo的列表里面取出最顶端对象, + * 画在画布上面即可 + */ + public void redo(){ + 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(); + } + } + /* + * 清空的主要思想就是初始化画布 + * 将保存路径的两个List清空 + * */ + public void removeAllPaint(){ + //调用初始化画布函数以清空画布 + initCanvas(); + invalidate();//刷新 + savePath.clear(); + deletePath.clear(); + } + +/* + * 保存所绘图形 + * 返回绘图文件的存储路径 + * + public String saveBitmap(){ + //获得系统当前时间,并以该时间作为文件名 + SimpleDateFormat formatter = new SimpleDateFormat ("yyyyMMddHHmmss"); + Date curDate = new Date(System.currentTimeMillis());//获取当前时间 + String str = formatter.format(curDate); + String paintPath = ""; + str = str + "paint.png"; + File dir = new File("/sdcard/notes/"); + File file = new File("/sdcard/notes/",str); + if (!dir.exists()) { + dir.mkdir(); + } + else{ + if(file.exists()){ + file.delete(); + } + } + + try { + FileOutputStream out = new FileOutputStream(file); + mBitmap.compress(Bitmap.CompressFormat.PNG, 100, out); + out.flush(); + out.close(); + //保存绘图文件路径 + paintPath = "/sdcard/notes/" + str; + + + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return paintPath; + }*/ + + + private void touch_start(float x, float y) { + mPath.reset();//清空path + 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(y - mY); + if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { + //mPath.quadTo(mX, mY, x, y); + 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); + savePath.add(dp); + mPath = null; + + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + float x = event.getX(); + float y = event.getY(); + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + + 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; + } + +} diff --git a/src/main/java/net/micode/notes/ui/BoardActivity.java b/src/main/java/net/micode/notes/ui/BoardActivity.java new file mode 100644 index 0000000..4098554 --- /dev/null +++ b/src/main/java/net/micode/notes/ui/BoardActivity.java @@ -0,0 +1,46 @@ +package net.micode.notes.ui; + +import android.app.Activity; +import android.os.Bundle; +import android.view.View; +import android.widget.ImageButton; + +import net.micode.notes.PaintView; +import net.micode.notes.R; + +public class BoardActivity extends Activity { + private PaintView paintView; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); //调用父类的功能 + this.setContentView(R.layout.activity_paint); + //根据id获取添加图片按钮 + final ImageButton undo = (ImageButton) findViewById(R.id.undo); + //为点击图片按钮设置监听器 + undo.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + paintView.undo(); + } + }); + + final ImageButton paint_reset = (ImageButton) findViewById(R.id.paint_reset); + //为点击图片按钮设置监听器 + paint_reset.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + paintView.redo(); + } + }); + + final ImageButton paint_delete = (ImageButton) findViewById(R.id.paint_delete); + //为点击图片按钮设置监听器 + paint_delete.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + paintView.removeAllPaint(); + } + }); + paintView = (PaintView)findViewById(R.id.paint_layout); + } +} diff --git a/src/main/res/drawable-hdpi/navigationbar_bg.png b/src/main/res/drawable-hdpi/navigationbar_bg.png new file mode 100644 index 0000000..2ea3923 Binary files /dev/null and b/src/main/res/drawable-hdpi/navigationbar_bg.png differ diff --git a/src/main/res/drawable-hdpi/paint.png b/src/main/res/drawable-hdpi/paint.png new file mode 100644 index 0000000..9ff3f18 Binary files /dev/null and b/src/main/res/drawable-hdpi/paint.png differ diff --git a/src/main/res/drawable-hdpi/paint_clor.png b/src/main/res/drawable-hdpi/paint_clor.png new file mode 100644 index 0000000..9cdcae9 Binary files /dev/null and b/src/main/res/drawable-hdpi/paint_clor.png differ diff --git a/src/main/res/drawable-hdpi/paint_delete.png b/src/main/res/drawable-hdpi/paint_delete.png new file mode 100644 index 0000000..88de254 Binary files /dev/null and b/src/main/res/drawable-hdpi/paint_delete.png differ diff --git a/src/main/res/drawable-hdpi/paint_reset.png b/src/main/res/drawable-hdpi/paint_reset.png new file mode 100644 index 0000000..5733e54 Binary files /dev/null and b/src/main/res/drawable-hdpi/paint_reset.png differ diff --git a/src/main/res/drawable-hdpi/undo.png b/src/main/res/drawable-hdpi/undo.png new file mode 100644 index 0000000..d410837 Binary files /dev/null and b/src/main/res/drawable-hdpi/undo.png differ diff --git a/src/main/res/layout/activity_paint.xml b/src/main/res/layout/activity_paint.xml new file mode 100644 index 0000000..3c178eb --- /dev/null +++ b/src/main/res/layout/activity_paint.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + \ No newline at end of file