import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import java.util.Iterator;
import java.util.Vector;
public class HuaBanView extends View {
private Bitmap cacheBitmap;
private Canvas cacheCanvas;
private Paint paint;
private Paint bitmapPaint;
private Path path;
private int height;
private int width;
private float pX;
private float pY;
private int paintColor = Color.RED;
private static Paint.Style paintStyle = Paint.Style.STROKE;
private static int paintWidth = 5;
private Canvas canvas;
private Stack pathList = new Stack(); //存放画笔路径
private Stack removedPathList = new Stack();//存放撤销的路径
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
height = h;
width = w;
init();
}
private void init() {
cacheBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
cacheCanvas = new Canvas(cacheBitmap); //保存之前的绘图
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
path = new Path();
bitmapPaint = new Paint();
updatePaint();
}
private void updatePaint() {
paint.setColor(paintColor);
paint.setStyle(paintStyle);
paint.setStrokeWidth(paintWidth);
}
public HuaBanView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public HuaBanView(Context context) {
super(context);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
path = new Path();
path.moveTo(event.getX(), event.getY());
pX = event.getX();
pY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
path.quadTo(pX, pY, (event.getX() + pX) / 2, (event.getY() + pY) / 2);
pX = event.getX();
pY = event.getY();
break;
case MotionEvent.ACTION_UP:
//拿起手指时才将其画在缓冲bitmap上
cacheCanvas.drawPath(path, paint);
pathList.push(path);
Log.e("xxx", path.toString());
Log.e("xxx", pathList.size() + "");
break;
}
//onmove的时候也会一直调用绘制实时图形
invalidate();
return true;
}
@Override
protected void onDraw(Canvas canvas) {
this.canvas = canvas;
Log.e("xxx", "canvas = " + canvas.toString());
Log.e("xxx", "绘制cacheBitmap");
//将之前的路径绘图绘制进新的画板上
canvas.drawBitmap(cacheBitmap, 0, 0, bitmapPaint);
//绘制最新的一个路径,如果没有这一句也能画上去,只不过是手抬起来才画上去。
canvas.drawPath(path, paint);
Log.e("xxx", "绘制最新一个路径");
}
public void undo() {
if (pathList != null && pathList.size() > 0) {
//调用初始化画布函数以清空画布
init();
//将路径保存列表中的最后一个元素删除 ,并将其保存在路径删除列表中
Path drawPath = pathList.pop();
removedPathList.push(drawPath);
//将路径保存列表中的路径重绘在画布上
Log.e("xxx-剩余步数", pathList.size() + "");
//将路径减少一个画到缓存画布上,再将缓存画布画到显示的画布上。
for (Path path : pathList.vector) {
cacheCanvas.drawPath(path, paint);
this.path = path;
Log.e("xxx", path.toString());
}
invalidate();
}
}
public void redo() {
if (removedPathList.size() > 0) {
//调用初始化画布函数以清空画布
init();
//将路径保存列表中的最后一个元素删除 ,并将其保存在路径删除列表中
Path drawPath = removedPathList.pop();
pathList.push(drawPath);
//将路径保存列表中的路径重绘在画布上
Iterator iter = pathList.vector.iterator(); //重复保存
while (iter.hasNext()) {
Path path = (Path) iter.next();
cacheCanvas.drawPath(path, paint); //https://www.it610.com/article/1294866028412608512.htm
}
invalidate();// 刷新
}
}
public void setColor(int color) {
paintColor = color;
updatePaint();
}
public void setPaintWidth(int width) {
paintWidth = width;
updatePaint();
}
public static final int PEN = 1;
public static final int PAIL = 2;
public void setStyle(int style) {
switch (style) {
case PEN:
paintStyle = Paint.Style.STROKE;
break;
case PAIL:
paintStyle = Paint.Style.FILL;
break;
}
updatePaint();
}
}