onDraw( )基础
Posted iblade
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了onDraw( )基础相关的知识,希望对你有一定的参考价值。
View 三大模块:布局,绘制,触摸反馈
绘制 四个层次:①Canvas,②Paint,③ Canvas辅助(范围剪切和几何变换),④绘制顺序(通过绘制方法控制)
重写绘制方法:onDraw( )
onDraw主体内容的绘制
绘制关键:Canvas【 翻译为 画布 但并不载体 就是个绘制工具】
Canvas的绘制方法:drawCircle,drawText等
关键参数 Paint 颜料画笔 风格信息: 阴影, 空心,抗锯齿等。
Canvas的辅助绘制:
绘制范围的裁切,clipXXX()
绘制内容的几何变换,Matrix
绘制顺序:使用不同绘制方法来控制遮盖关系(控制绘制顺序解决的并不是「做不到」的问题,而是性能问题。同样的一种效果,你不用绘制顺序的控制往往也能做到,但需要用多个 View 甚至是多层 View 才能拼凑出来,因此代价是 UI 的性能;而使用绘制顺序的控制的话,一个 View 就全部搞定了。)
范围裁切有两个方法: clipRect() 和 clipPath()。裁切方法之后的绘制代码,都会被限制在裁切范围内。
canvas.drawCircle(300, 300, 200, paint)
圆心坐标和半径,这些都是圆的基本信息,也是它的独有信息。什么叫独有信息?就是只有它有,别人没有的信息。你画圆有圆心坐标和半径,画方有吗?画椭圆有吗?这就叫独有信息。独有信息都是直接作为参数写进 drawXXX() 方法里的(比如 drawCircle(centerX, centerY, radius, paint) 的前三个参数)。
而除此之外,其他的都是公有信息。比如图形的颜色、空心实心这些,你不管是画圆还是画方都有可能用到的,这些信息则是统一放在 paint 参数里的。
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Paint.setAntiAlias(boolean aa); //或者动态开关抗锯齿。
所谓的毛边或者锯齿,发生的原因并不是很多人所想象的「绘制太粗糙」「像素计算能力不足」;同样,抗锯齿的原理也并不是选择了更精细的算法来算出了更平滑的图形边缘。
实质上,锯齿现象的发生,只是由于图形分辨率过低,导致人眼察觉出了画面中的像素颗粒而已。换句话说,就算不开启抗锯齿,图形的边缘也已经是最完美的了,而并不是一个粗略计算的粗糙版本。
那么,为什么抗锯齿开启之后的图形边缘会更加平滑呢?因为抗锯齿的原理是:修改图形边缘处的像素颜色,从而
让图形在肉眼看来具有更加平滑的感觉
。一图胜千言,上图:
右侧
从某种角度讲,它也造成了图形的颜色失真。
所以,抗锯齿好不好?好,大多数情况下它都应该是开启的;但在极少数的某些时候,你还真的需要把它关闭。「某些时候」是什么时候?到你用到的时候自然就知道了。例如很多万恶的马赛克,是不是很讨厌?
canvas.drawArc(300,300,800,800,45,135,true,paint);
drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint) 绘制弧形或扇形
paint.setStyle(Paint.Style.FILL); // 填充模式
canvas.drawArc(200, 100, 800, 500, -110, 100, true, paint); // 绘制扇形
canvas.drawArc(200, 100, 800, 500, 20, 140, false, paint); // 绘制弧形(不仅过圆心)
paint.setStyle(Paint.Style.STROKE); // 画线模式
canvas.drawArc(200, 100, 800, 500, 180, 60, false, paint); // 绘制不封口的弧形
Path 可以描述直线、二次曲线、三次曲线、圆、椭圆、弧形、矩形、圆角矩形。把这些图形结合起来,就可以描述出很多复杂的图形。
Path 有两类方法,一类是直接描述路径的,另一类是辅助的设置或计算。
这一类方法还可以细分为两组:添加子图形和画线(直线或曲线)
第一组: addXxx() ——添加子图形
addCircle(float x, float y, float radius, Direction dir) 添加圆
第二组:xxxTo() ——画线(直线或曲线)
这一组和第一组 addXxx() 方法的区别在于,第一组是添加的完整封闭图形(除了 addPath() ),而这一组添加的只是一条线。
lineTo(float x, float y) / rLineTo(float x, float y) 画直线
从当前位置向目标位置画一条直线, x 和 y 是目标位置的坐标。这两个方法的区别是,lineTo(x, y) 的参数是绝对坐标,而 rLineTo(x, y) 的参数是相对当前位置的相对坐标 (前缀 r 指的就是 relatively 「相对地」)。
paint.setStyle(Style.STROKE);
path.lineTo(100, 100); // 由当前位置 (0, 0) 向 (100, 100) 画一条直线
path.rLineTo(100, 0); // 由当前位置 (100, 100) 向正右方 100 像素的位置画一条直线
quadTo(float x1, float y1, float x2, float y2) / rQuadTo(float dx1, float dy1, float dx2, float dy2) 画二次贝塞尔曲线
moveTo(float x, float y) / rMoveTo(float x, float y) 移动到目标位置
不论是直线还是贝塞尔曲线,都是以当前位置作为起点,而不能指定起点。但你可以通过 moveTo(x, y) 或 rMoveTo() 来改变当前位置,从而间接地设置这些方法的起点
arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) arcTo() 只用来画弧形而不画扇形,所以不再需要 useCenter 参数;而多出来的这个 forceMoveTo 参数的意思是,绘制是要「抬一下笔移动过去」,还是「直接拖着笔过去」,区别在于是否留下移动的痕迹。
close() 封闭当前子图形
各路大神
Android自定义控件三部曲文章索引
以上是关于onDraw( )基础的主要内容,如果未能解决你的问题,请参考以下文章
onDraw( ) 和 dispatchDraw( ) 的区别
[vscode]--HTML代码片段(基础版,reactvuejquery)
Invalidate()不会在Xamarin.Android中调用OnDraw()