图形绘制的基本要素:
1.onDraw(Canvas) --- 所有的尺寸都是像素
2.Canvas
3.Paint
4.坐标系
5.尺寸单位
onDraw绘图api
1.drawColor() ----------- 画颜色
2.drawLine() ----------- 画线
3.drawRect() ----------- 画矩形
4.drawRoundRect() ----- 画带有圆角的矩形
5.drawCircle() ---------- 画圈
6.drawOval(). ----------- 画圆
7.drawArc() ---------- 画弧
8.drawPaint() ---------- 画笔
9.DrawPath() ---------- 画轨迹
10.drawBitmap -------- 画图像
11.drawText() --------- 画文本
Path. ------ api
addxxx().
moveTo().
xxxTo()
PathMeasure().
setFillType()
画线
[图片上传中...(image.png-900126-1575875471719-0)]
画圆
image.pngonSizeChanged方法
这个方法是在onMeasure方法后调用,如果测量的结果不一样,这个方法会被调用。
Path画圆
path.addCircle(getWidth()/2,getHeight()/2,RADIUS, Path.Direction.CCW)
我讲下第四个参数,
Path.Direction.CW表示的是顺时针,Path.Direction.CCW逆时针
它的作用是多个图形的填充规则
为了更好的了解上面的参数,我们在画一个矩形
矩形图形代码:
path.addRect(getWidth()/2-RADIUS,getHeight()/2,getWidth()/2+RADIUS,getHeight()/2+RADIUS*2,Path.Direction.CCW);
图形如下:
image.png
现在我们再把矩形的CCW改为CW,又会是怎样的效果呢?
image.png
还有种方法是通过api path.setFillType()来填充
它有四种状态 分别是EVEN_ODD,INVAESE_EVEN_ODD,INVERSE_WINDING,WINDING
它们分别表示奇数填充,奇数反方向填充也就是偶数。包含取反填充和包含填充,后面两种应该很好理解,前面两种就不是那么好理解了。
其实他在绘制图形的时候是有一定的规则的,也就是如果是逆时针记为1。顺时针记为-1 相交处累加。图形解释如下:
image.png
我们在画一个比较大的圆。代码如下:
path.addCircle(getWidth()/2,getHeight()/2,RADIUS*2,Path.Direction.CCW);
运行结果如下:
image.png
自定义仪表盘
1.定义DashBoardView继承View
2.初始化画笔Paint
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private void init(){
paint.setStrokeWidth(4);
paint.setStyle(Paint.Style.STROKE);
}
3.定义圆弧的大小以及劣弧的角度
private static final int RADIUS = DisplayUtils.dpToPx(150);
private static final int ANGLE = 120;
4.onDraw()方法使用canvas.drawArc
canvas.drawArc(getWidth()/2-RADIUS,getHeight()/2-RADIUS,
getWidth()/2+RADIUS,getHeight()/2+RADIUS,90+ANGLE/2,
360-ANGLE,false,paint);
先试下效果:
image.png
弧线画好了,接下来我们在画下刻度
1.实例化 Path dash = new Path()
2.定义刻度大小
dash.addRect(0,0,DisplayUtils.dpToPx(2),DisplayUtils.dpToPx(10), Path.Direction.CCW);
3.画刻度:
pathMeasure的作用就是计算轨迹的长度,我这里是画20刻度,这里就是用的轨迹长度减去刻度的宽度除以20 得到刻度之间的间隔宽度。
path.addArc(getWidth()/2-RADIUS,getHeight()/2-RADIUS,
getWidth()/2+RADIUS,getHeight()/2+RADIUS,90+ANGLE/2,
360-ANGLE);
pathMeasure = new PathMeasure();
pathMeasure.setPath(path,false);
pathDashPathEffect = new PathDashPathEffect(dash,(pathMeasure.getLength()-DisplayUtils.dpToPx(2))/20,0, PathDashPathEffect.Style.ROTATE);
刻度这里就算画好了 接下来我们画指针
先设置指针长度:private static final int LENTH = DisplayUtils.dpToPx(100)
此处用到了正余弦相关的知识Math.cos()填入的内容为弧度,这里我们需要把角度转换为弧度Math.toRadians()
canvas.drawLine(getWidth()/2,getHeight()/2,
getWidth()/2+(float)Math.cos(Math.toRadians(getAngleForMark(5)))*LENTH,
getHeight()/2 + (float)Math.sin(Math.toRadians(getAngleForMark(5)))*LENTH,paint);
角度:
private float getAngleForMark(int mark){
return 90 + ANGLE/2 + (360 - ANGLE)/20 * mark;
}
效果图:
image.png
xfermode的使用
我这里使用xfermode做了一个头像的剪裁,核心代码如下:
Xfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
canvas.drawOval(border,paint);
int saveCount = canvas.saveLayer(cut,paint);
canvas.drawOval(cut,paint);
paint.setXfermode(xfermode);
canvas.drawBitmap(avatar,PADDING,PADDING,paint);
paint.setXfermode(null);
canvas.restoreToCount(saveCount);
对于xfermode我们主要关注的就是选择的mode-PorterDuff.Mode.xxx
而对于选择的mode,那么我们就要对不同的mode它们的作用有所了解,为了了解这个mode,我们可以从developers中寻找答案:
原始图形:
image.png
选择不同mode的图形如下:
ADD
image.pngCLEAR
image.pngDARKEN
image.pngDST
image.pngDST_ATOP
image.pngDST_IN
image.pngDST_OUT
image.pngDST_OVER
image.pngLIGHTEN
image.pngMULTIPLY
image.pngOVERLAY
image.pngSCREEN
image.pngSRC
image.png
SRC_ATOP
image.pngSRC_IN
image.pngSRC_OUT
image.pngSRC_OVER
image.pngXOR
image.png其实这些view还是有些粗糙的,今后有时间把仪表盘做成指南针或者速度仪。自定义头像可以做成项目中灵活引用可以自己设置参数,还有一个东西没讲到就是饼状图。我已经把这些自定义的东西已经上传到了github
源码
网友评论