一、概述:
这次作为记录自定义View学习有关onDraw方法及其api和Paint类和canvas类的学习。在onDraw方法中有canvas方法其实初级阶段也主要是canvas和paint的使用。使用这两个类就必须要知道这两个类的所有api方法,有人说这些api太多只有用到的时候再去查。我不敢苟同,自己都不知道有这个方法实现,自己怎么可能去查这个方法呢。或许有人分析功能时,分析的恰到好处。然后再去查询对应所需要的方法,但是我自己这个阶段是不怎么会分析,更多的是看到一些绚丽的功能,去查看此源代码,看代码去分析功能的实现以及api的调用。(注:有个详细自定义的教程给出网址:点击打开链接,gcssloop大神的自定义View我也是看了他的文章进行学习总结)
二、canvas:
canvas的api还是比较多的,不过还是要全部看进去,就算只有三分之一的被记住,但也总比不看要好。
clipPath:将当前剪辑与指定路径相交。
clipRect:将当前剪辑与指定的矩形相交,该矩形以局部坐标表示。
concat:用指定的矩阵预处理当前矩阵。
drawARGB:用指定的ARGB颜色填充整个画布的位图。
drawArc: 绘制指定的弧。
drawBitmap:绘制位图。
drawBitmapMesh:通过网格绘制位图,其中网格顶点均匀分布在位图中。
drawCircle:绘制指定的圆。
drawColor:用指定的颜色填充整个画布的位图。
drawLine:画线条。
drawLines:画一系列线条。
drawOval:绘制椭圆。
drawPaint:用指定的油漆填充整个画布的位图(限于当前剪辑)。
drawPatch:使用指定的绘图绘制指定的路径。
drawPicture:绘制图片。
drawPoint:用于绘制单个点。
drawPoints:画出一系列点。
drawRGB:用指定的RGB颜色填充整个画布的位图。
drawRect:指定的绘图绘制指定的Rect。
drawRoundRect:绘图绘制指定的圆角。
drawText:绘制指定范围的文本。
drawTextOnPath:沿着指定的路径使用指定的绘图绘制文本。
drawTextRun:在单一方向上绘制一段文本,并带有用于复杂文本整形的可选上下文。
drawVertices: 绘制顶点数组,解释为三角形(基于模式)。
getClipBounds:检索当前剪辑的边界(以本地坐标)。
getDensity:返回画布的目标密度。
getDrawFilter:绘画过滤。
getHeight:返回当前绘图图层的高度。
getMaximumBitmapHeight:返回使用此画布绘制的位图的最大允许高度。
getMaximumBitmapWidth:返回使用此画布绘制的位图的最大允许宽度。
getSaveCount:返回Canvas专用堆栈上矩阵/剪辑状态的数量。
getWidth:返回当前绘图图层的宽度。
isHardwareAccelerated:指示此Canvas是否使用硬件加速。
isOpaque:如果当前图层绘制的设备不透明,则返回true。
quickReject:如果指定矩形在被当前矩阵转换后完全位于当前剪辑之外,则返回true。
restore:此调用将先前调用save(),并用于从上次保存调用后删除对矩阵/剪辑状态的所有修改。
restoreToCount:有效的方式来弹出任何调用save()之后发生的保存计数达到saveCount。
rotate:用指定的旋转预先缩放当前矩阵。
save:保存当前矩阵并剪辑到私有堆栈上。
saveLayer:它的行为与save()相同,但是它还分配并将图形重定向到屏幕外渲染目标。
saveLayerAlpha:方便saveLayer(RectF, Paint)但不是取整个Paint对象,而只取alpha参数。
scale:用指定的比例预先缩放当前矩阵。
setBitmap:指定要绘制的画布的位图。
setDensity:指定此Canvas的支持位图的密度。
setMatrix:用指定的矩阵完全替换当前矩阵。
skew:用指定的偏斜对当前矩阵进行预先扫描。
translate:用指定的转换对当前矩阵进行预处理。
作为android工程师对于画布的操作应该都是了如指掌,只是缺乏编写的经验而已,绘制图形类似圆、椭圆、矩形等都只是api的调用。但是关于画布的移动操作比如缩放,平移,旋转等等。需要注意了解一下
1、平移
translate方法接收,x和y坐标。平移后在x的左侧和y的上边都是负值,其实这个很容易理解。但是获取屏幕坐标的时候会发现 自己点的地方和要显示的地方不一样
所点击的地方和实际绘制的地方其实有所不同,也就是说在左上范围。此时的交互会有一定的问题。在绘制的时候确实 圆心坐标到了中心位置,并且绘制也是从中心开始的在绘制的时候确实没有问题 但是,在点击的时候,是获取的屏幕坐标系的位置,而绘制的时候是根据屏幕坐标进行绘制。简单的来说,我在屏幕上点击(100,100)的位置 而实际绘制却是中心为原点(100,100)的位置,两个位置差了一个画布移动的距离
解决这个问题其实可以用matrix但是我不知道为什么Matrix matrix = canvas.getMatrix()会被遗弃。希望有大神们指点一下。除了这个方法还能如何解决。我参照gcssloop大神的博客。解决方案如下:
在需要绘制交互点击的点转为画布上的点。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float[] pts = {mX,mY};
canvas.save();
canvas.translate(getWidth()/2,getHeight()/2);
Matrix matrix = canvas.getMatrix();
Matrix matrix1 = new Matrix();
matrix.invert(matrix1);
matrix1.mapPoints(pts);
canvas.drawCircle(pts[0],pts[1],30,mPaint);
canvas.restore();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
int x = (int) event.getX();
int y =(int) event.getY();
mX=x;
mY=y;
invalidate();
break;
case MotionEvent.ACTION_UP:
mX=0;
mY=0;
invalidate();
break;
}
return true;
}
2、旋转
画布选择,与一般的画图有所区别,毕竟正常绘制图形想画哪里就画哪里。但是如果位置点比较复杂。可能都无法计算时,可选择平移旋转进行绘制,比如雷达图,钟表等很典型的例子。此时极坐标系用处就比较大了。这里需要注意到是对于(sx,sy)的取值直接影响绘图
取值范围 | 说明 |
(-∞,-1) | 先根据缩放中心放大n倍,再根据中心轴进行翻转 |
-1 | 根据缩放中心轴进行翻转 |
(-1,0) | 先根据缩放中心缩小到n,再根据中心轴进行翻转 |
0 | 不会显示,若sx为0,则宽度为0,不会显示,sy同理 |
(0,1) | 根据缩放中心缩小到n |
1 | 没有变化 |
需要理解的是负数就是围绕中心轴旋转,也就是所谓的缩放中心。scale(float sx, float sy, float px, float py)中后两个参数就是缩放中心,默认是坐标原点。
3、错切
坐错切需要理解的是其参数的意思:
float sx:将画布在x方向上倾斜相应的角度,sx倾斜角度的tan值,
float sy:将画布在y轴方向上倾斜相应的角度,sy为倾斜角度的tan值。
说真的自己还没有怎么使用过。