做Android不知不觉也有些年头了,但是对于自定义view却没有真正的好好研究或者实践过,可能是好用的库太多,自己就不想去想着自己去实现一些效果,不过别人的终究是别人的,毕竟“纸上得来终觉浅,绝知此事要躬行”,所以最近就花了些时间从最基础的开始实践,以此博客做一些记录。
说起自定义view大家肯定首先想到的就是canvas和paint,canvas大家一般都直译为“画布”而paint大家直译为“画笔”,那咱们看看Android怎么说的:
The Canvas class holds the "draw" calls. To draw something, you need 4 basic components: A Bitmap to hold the pixels, a Canvas to host the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect,Path, text, Bitmap), and a paint (to describe the colors and styles for the drawing).
用我蹩脚的英语翻译一下大概就是:canvas类掌握着draw方法的调用,为了绘制一些东西,你需要4个基础的组件:一个bitmap来承载像素,一个canvas来调用draw(写入一些东西到bitmap),一个绘制的基础位图(例如rect矩形,path路径,text文本,bitmap图像)和一支画笔(用来描述绘制过程的颜色以及样式)。那咱们再来看paint:
The Paint class holds the style and color information about how to draw geometries, text and bitmaps.
翻译:paint类掌握着关于如何绘制几何图形,文本,图像的样式以及颜色信息。看了google的解释我们好像明白了,其实canvas才是绘制的主角,paint只是其绘制需要的一部分而已呀,了解了咱们要用到的东西,再看看canvas和paint怎么用以及这些绘制的代码应该写在哪里吧,我们一般如果要自定义view要么是继承自现有控件,要么继承自view或者viewgroup了,但是其实最终不都是继承自view么?view才是所有view的祖宗吧,要实现绘制我们必然要重写一个onDraw()方法,它的Android解释是:Implement this to do your drawing.意思是实现这个方法去做自己的绘制,那么我们把需要绘制的代码写在这个方法里面好了。
接下来咱们来进行具体的绘制,咱们上面也说了paint是canvas进行绘制必不可少的一部分,那就先看看paint的一些用法,大家想啊,绘制肯定会有颜色,所以有setColor方法,如果是画线什么的肯定得有粗细,所以有setStrokeWidth方法设置画笔的粗细,还有setStyle方法是用来设置paint画笔的风格的,因为我们会绘制一些封闭图形,那么到底是不是要填充呢?就是这个方法设置的,绘制文字要设置文字大小,那么所以还会有setTextSize方法,其实还有一个设置是否抗锯齿的方法setAntiAlias,这个方法的作用就是让绘制出来的内容看起来更加平滑一些,paint常用的方法就这么多,好,画笔有了那咱们看看如何用画笔绘制内容吧,接下来咱们看看canvas的一些方法。
- canvas.drawColor(@ColorInt int color) 设置canvas的背景色,也即画布的颜色
- canvas.drawCircle(float cx, float cy, float radius, @NonNull Paint paint) 画圆,前两个参数是圆心坐标(x,y),第三个参数是圆的半径,第四个参数是画笔,Android里面的坐标系的坐标原点跟上学时候学习的平面直角坐标系不一样,Android的坐标原点(0,0)在手机的左上角,水平向右为x的正值,水平向下的y为正值,其他两个方向自然相反,所以也就可以大概想象上面画的圆大概在什么位置了,同样有同学说这个圆是空心的还是实心的呀,那么就用上面paint的setStyle来设置了,如果传入参数值是Paint.Style.FILL则是实心的,如果是Paint.Style.STROKE则是空心的
- canvas.drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)画矩形,前四个参数指的是四条边距离x轴和y轴的距离,这么解释下(假设四个值都为正的情况,一般也不需要负的,如果是负的,都跑出屏幕了),left数值指的是矩形左边距离y轴有多远(假设在这个距离处画一条y轴平行的无限延伸的直线),top数值则是指矩形上边距离x轴有多远(假设在这个距离处画一条x轴平行的无限延伸的直线),bottom数值则是指矩形下边距离x轴有多远(假设在这个距离处画一条x轴平行的无限延伸的直线),right则是指矩形右边距离y轴有多远(假设在这个距离处画一条y轴平行的无限延伸的直线),那咱们就有四条无线延伸的直线了, 那么在这个平面内肯定会相交的,那么四条直线相交得到的矩形就是我们绘制出来的矩形,见到有些文章解释说是(left, top)和(right, bottom) 分别是矩形左上角以及右下角的坐标,其实这样子解释也没错,因为结果都是一样子的,毕竟我们结果导向嘛,哈哈
- canvas.drawPoint(float x, float y, @NonNull Paint paint)顾名思义画点,前两个参数就是点的坐标,后面是画笔。但是这个点也会有点形状,可以通过paint的setStrokeCap方法来设置,其中传入参数Paint.Cap.BUTT是方点,传入Paint.Cap.ROUND是圆点,还有个是Paint.Cap.SQUARE也是方点,这个方法觉得有一丝丝鸡肋呀,因为画方或者画圆不是有现成的方法么?并且还能调节大小呢
- canvas.drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)画椭圆,这个参数跟画矩形是类似的,只不过是在矩形的四个顶点上作出的椭圆,同样大家可以这样试下,就是如果这四个点按照绘制正方向传入,那么最终得到的圆就是正圆而不是椭圆了
- canvas.drawLine(float startX, float startY, float stopX, float stopY,@NonNull Paint paint)画直线,大家也都知道两个点能够确定一条直线,所以前面四个参数就是指线的起点以及终点的坐标,paint是画笔
- canvas.drawLines(@Size(multiple=4) @NonNull float[] pts, @NonNull Paint paint)一次性画多条直线,但是这个函数第一个参数是一个float类型的数组,且数组元素个数必须是4的倍数,每相邻的两个点确定一条直线,所以它不能把上一条直线的终点当做下一条直线的起点的,所以可能会有同样的坐标写两遍了,其实这样子也有好处,就是可以画两条没有一点关系的直线,可以是平行的等等
- canvas.drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,@NonNull Paint paint)画圆角矩形,前面四个参数就不说了,因为跟矩形是一样一样的,在说(rx,xy)这两个参数意思之前,先说下就是圆角矩形的圆角是按照椭圆绘制的,至少注释是这么写@param rx The x-radius of the oval used to round the corners,@param ry The y-radius of the oval used to round the corners,其中rx和ry意思就是用于圆角的椭圆的x和y坐标,但是我们为啥画出来的圆角矩形的圆角还是比较正圆的呢?看起来也不是椭圆啊,那是因为我们rx和ry设置的值是相同的,所以是按照正圆来画的圆角,参考上面用drawOval的方法绘制正圆
- canvas.drawArc(float left, float top, float right, float bottom, float startAngle,float sweepAngle, boolean useCenter, @NonNull Paint paint)绘制弧线或者扇形,usercenter参数就是指定绘制扇形还是弧线的,前面的left,top,right,bottom则是跟绘制椭圆是一样的,为啥绘制弧线或者扇形跟椭圆有关呢?因为这个方法的注释有这么一句:Draw the specified arc, which will be scaled to fit inside the specified oval.大概意思就是绘制一个arc,这个arc将被缩放以用来适应在特定的椭圆内部。其中startAngle指代绘制的起始角度,既然有起始角度,那么肯定需要一个基准线呀,基准线就是水平向右,可以认为是手机坐标系中x轴,以此为基准那么顺时针滑动,就是正角度,如果逆时针滑动,那么就是负角度,所以如果startAngle=0,那么就是从水平向右开始,如果startAngle=45,那么就是从水平向右顺时针滑动45度处开始绘制了,那如果是startAngle=-45度呢,就是水平向右方向逆时针滑动45度作为开始绘制处了,而sweepAngle则是从startAngle处划过的角度,切记一定是划过的角度而不是最终到的角度,我刚开始老把它当做终止的角度,就搞错了,关于startAngle还有一点就是如果它是负值或者大于等于360度,那么起始角度就会跟360求模,得到的值作为起始角度。而关于sweepAngle还有一点就是如果其大于等于360,那么就会绘制出来一个完整的椭圆(或者一个椭圆形弧线了),如果这个是负值,同样也会跟360求模之后进行旋转绘制
- canvas.drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint):绘制图片,bitmap就是要绘制展示的图片bitmap对象,(left,top)就类比成图片左上角所在的坐标吧,相对好理解,最后paint就是画笔,将图片绘制在canvas上面,其实还有关键点就是paint设置了一些属性之后,例如设置一些模糊效果啊例如BlurMaskFilter图片的展示就会不同,所以还有别的应用,我们后面在讲
- drawText(@NonNull String text, float x, float y, @NonNull Paint paint):绘制文本,但是除了单纯的用paint设置文本大小以及颜色之外,还有其他的效果例如给文字添加阴影啊,用paint的setShadowLayer方法,我们后面会讲
本文详细介绍了在Android中自定义View时如何使用canvas和paint进行图形绘制。通过canvas的draw方法和paint的样式及颜色设置,讲解了如何绘制圆、矩形、线条、点等图形,并探讨了坐标系统和画布的背景色设置。同时,提到了paint的抗锯齿、文本绘制及图片展示等特性。
1260

被折叠的 条评论
为什么被折叠?



