需求功能详解
单纯的编辑图片的功能,能够在界面上进行图形的绘制,线条的涂鸦,和画马赛克的绘制,并且有撤销的功能。
画图形
继续上一篇的内容,涂鸦已经完成,接下来我们一起来完成画图形的操作:这里看到我暂时提供了四种图形的绘制:
可以看到有 矩形, 椭圆, 圆形, 箭头四种图形,除了箭头,其他三种图形都很简单。
实现思路
这里先说除了箭头的三种图形的绘制吧。要想绘制一个图形,只需要明白两个知识点就行了:
- 需要绘制什么图形
- 按下的点和终点,两个点就能确定一个四边框框,我们所要绘制的图形,其实就由这个四边框确定位置和大小
下面已绘制矩形为例
首先设置基础画笔:
if (mode == MODE.GRAPH_MODE) {
mTempPaint = new Paint();
mTempPaint.setAntiAlias(true);
mTempPaint.setColor(mPaintColor);
mTempPaint.setStrokeWidth(mPaintWidth);
mTempPaint.setStrokeCap(Paint.Cap.ROUND);
mTempPaint.setStrokeJoin(Paint.Join.ROUND);
}
创建保存图形绘制的队列,同样是为了更好的管理绘制和撤销操作:
private ArrayList mGraphPath = new ArrayList<>();
这里存储的实例与之前涂鸦功能的略有不同,需要记录按下时的坐标,和不断移动的结束坐标,以及所画图形的种类:
class DrawGraphBean {
public float startX, startY, endX, endY;
public GRAPH_TYPE type;
public Paint paint;
DrawGraphBean(float startX, float startY, float endx, float endY, GRAPH_TYPE type, Paint paint) {
this.startX = startX;
this.startY = startY;
this.endX = endx;
this.endY = endY;
this.type = type;
this.paint = paint;
}
}
给图形种类给出枚举(不进行设置,默认是矩形):
public enum GRAPH_TYPE {
RECT, CIRCLE, OVAL, ARROW
}
明白了原理和思路,真正画起来,就简单多了,同样在Action_Down
中记下起始点,画笔,然后添加到队列中:
if (mMode == MODE.GRAPH_MODE) {
mStartX = event.getX();
mStartY = event.getY();
setModePaint(mMode);
// 添加到队列中
DrawGraphBean graphBean = new DrawGraphBean(mStartX, mStartY, mStartX, mStartY, mCurrentGraphType, mTempPaint);
mPaths.add(mMode);
mGraphPath.add(graphBean);
}
然后在Action_Move
中,取出队列的最后一条数据,将他的终点坐标进行更新,那么在onDraw()
绘制时,就能画出不断跟随手指改变的图形了:
if (mMode == MODE.GRAPH_MODE && mGraphPath.size() > 0) {
DrawGraphBean tempBean = mGraphPath.get(mGraphPath.size() - 1);
tempBean.endX = mMoveX;
tempBean.endY = mMoveY;
}
在Action_Up
中只需要将新建的画笔置空即可:
mTempPaint = null;
最后,在onDraw()
中,将队列中的图形一一绘制出来即可:
/**
* 画图形
*/
private void drawGraphs(Canvas canvas) {
if (mGraphPath.size() > 0) {
for (DrawGraphBean graphBean : mGraphPath) {
if (graphBean.type == GRAPH_TYPE.RECT) {
graphBean.paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(graphBean.startX, graphBean.startY, graphBean.endX, graphBean.endY, graphBean.paint);
} else if (graphBean.type == GRAPH_TYPE.OVAL) {
graphBean.paint.setStyle(Paint.Style.STROKE);
canvas.drawOval(new RectF(graphBean.startX, graphBean.startY, graphBean.endX, graphBean.endY), graphBean.paint);
} else if (graphBean.type == GRAPH_TYPE.CIRCLE) {
graphBean.paint.setStyle(Paint.Style.STROKE);
// 计算半径
float radius = Math.min(Math.abs(graphBean.startX - graphBean.endX), Math.abs(graphBean.startY - graphBean.endY)) / 2;
float centerX, centerY;
centerX = graphBean.endX >= graphBean.startX ? graphBean.startX + radius : graphBean.startX - radius;
centerY = graphBean.endY >= graphBean.startY ? graphBean.startY + radius : graphBean.startY - radius;
canvas.drawCircle(centerX, centerY, radius, graphBean.paint);
} else if (graphBean.type == GRAPH_TYPE.ARROW) {
graphBean.paint.setStyle(Paint.Style.FILL);
drawArrow(graphBean.startX, graphBean.startY, graphBean.endX, graphBean.endY, canvas, graphBean.paint);
}
}
}
}
代码粗解:从onDraw()
中画图形的部分可以看出,根据图形的种类,分别进行了对应的绘制操作:除了箭头的图形,Canvas
都已经给我们提供了系统方法,分别是drawRect
,drawOval
和drawCircle
,只有画圆形,需要简单的计算,其他都是一句话搞定~
- 最后再讲解一下箭头的绘制
画箭头的方法,其实类似于系统提供的画Rect等操作,其实就是把Path
连接起来,绘制成的特殊的图形:
/**
* 画箭头
*/
private void drawArrow(float sx, float sy, float ex, float ey, Canvas canvas, Paint paint) {
int size = 8;
int count = 30;
float x = ex - sx;
float y = ey - sy;
double d = x * x + y * y;
double r = Math.sqrt(d);
float zx = (float) (ex - (count * x / r));
float zy = (float) (ey - (count * y / r));
float xz = zx - sx;
float yz = zy - sy;
double zd = xz * xz + yz * yz;
double zr = Math.sqrt(zd);
Path triangle = new Path();
triangle.moveTo(sx, sy);
triangle.lineTo((float) (zx + size * yz / zr), (float) (zy - size * xz / zr));
triangle.lineTo((float) (zx + size * 2 * yz / zr), (float) (zy - size * 2 * xz / zr));
triangle.lineTo(ex, ey);
triangle.lineTo((float) (zx - size * 2 * yz / zr), (float) (zy + size * 2 * xz / zr));
triangle.lineTo((float) (zx - size * yz / zr), (float) (zy + size * xz / zr));
triangle.close();
canvas.drawPath(triangle, paint);
}
只需要给出起点和终点坐标,还有一点需要注意的是,箭头的画笔需要设置成实心的,那么箭头就绘制完成了~
相关文章
Android 编辑图片 Canvas画图,涂鸦,马赛克等(一)
Android 编辑图片 Canvas画图,涂鸦,马赛克等(三)
- 项目代码
最后奉上完整的项目代码,欢迎clone和star和意见提交:
https://github.com/wx9265661/SmallDemos2