自定义View学习笔记 From GcsSloop

首先强烈感谢GcsSloop推出的自定义View系列文章,地址http://www.gcssloop.com/customview/CustomViewIndex。好记性不如烂笔头,特将学习总结以本博客做记录:

一:基础部分

1.坐标系

三个系列方法:
    getLeft():距离父容器左
    getX():距离自身x轴
    getRawX():距离屏幕x轴

2.角度与弧度

180(角度)/deg = π(弧度)/rad

3.颜色

**颜色定义**
ARGB8888    四通道高精度32位   #FFFFFFFF
ARGB4444    四通道低精度16位   #FFFF
RGB565      屏幕默认16位
Alpha8          仅有透明通道8位
**混合模式**
RGB最终颜色=绘制的颜色+(1-绘制颜色的透明度)*Canvas的原色
*绘制颜色/原色=RGB*A(浮点 0~255--0.0f~1.0f)
*demo:0x88ffffff(色) = 0xffffff * (0x88/0xff)
核心代码 Paint.setfermode(Porter.MODE)

自定义View学习笔记 From GcsSloop_第1张图片

二:进阶

1.流程

(1):构造器:布局文件引用一般调用双参数的方法
(2):onMeasure()
确定大小,如果对View的宽高进行修改了,不要调用 super.onMeasure( widthMeasureSpec, heightMeasureSpec); 要调用 setMeasuredDimension( widthsize, heightsize); 这个函数。
(3):onSizeChanged():这里的w,h就是最终的大小
(4):onLayout():child.layout(l,t,r,b)
(5):onDraw()
(6):公共方法与回调接口

2.Canvas

> 1.速查表
(1)绘制颜色 drawColor, drawRGB, drawARGB 使用单一颜色填充整个画布
(2)绘制基本形状 drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc 依次为 点、线、矩形、圆角矩形、椭圆、圆、圆弧
(3)绘制图片 drawBitmap, drawPicture 绘制位图和图片
(4)绘制文本 drawText, drawPosText, drawTextOnPath 依次为 绘制文字、绘制文字时指定每个文字位置、根据路径绘制文字
(5)绘制路径 drawPath 绘制路径,绘制贝塞尔曲线时也需要用到该函数
(6)顶点操作 drawVertices, drawBitmapMesh 通过对顶点操作可以使图像形变,drawVertices直接对画布作用、 drawBitmapMesh只对绘制的Bitmap作用
(7)画布剪裁 clipPath, clipRect 设置画布的显示区域
(8)画布快照 save, restore, saveLayerXxx, restoreToCount, getSaveCount 依次为 保存当前状态、 回滚到上一次保存的状态、 保存图层状态、 回滚到指定状态、 获取保存次数
(9)画布变换 translate, scale, rotate, skew 依次为 位移、缩放、 旋转、错切
(10)Matrix(矩阵) getMatrix, setMatrix, concat 实际上画布的位移,缩放等操作的都是图像矩阵Matrix, 只不过Matrix比较难以理解和使用,故封装了一些常用的方法。
2.画布操作
(1)位移(translate):移动的是坐标系
(2)缩放(scale):
[-∞, -1)===先根据缩放中心放大n倍,再根据中心轴进行翻转
-1 ===根据缩放中心轴进行翻转
(-1, 0)===先根据缩放中心缩小到n,再根据中心轴进行翻转
0===不会显示,若sx为0,则宽度为0,不会显示,sy同理
(0, 1)===根据缩放中心缩小到n
1===没有变化
(1, +∞)===根据缩放中心放大n倍
(3)旋转(rotate):可叠加
(4)错切(skew)
参数含义:
float sx:将画布在x方向上倾斜相应的角度,sx倾斜角度的tan值,
float sy:将画布在y轴方向上倾斜相应的角度,sy为倾斜角度的tan值.
变换后:
X = x + sx * y
Y = sy * x + y
(5)快照(save)和回滚(restore)
save 把当前的画布的状态进行保存,然后放入特定的栈中
saveLayerXxx 新建一个图层,并放入特定的栈中
restore 把栈中最顶层的画布状态取出来,并按照这个状态恢复当前的画布
restoreToCount 弹出指定位置及其以上所有的状态,并按照指定位置的状态进行恢复
getSaveCount 获取栈中内容的数量(即保存次数)
3.图片文字
(1)drawPicture:
:在AndroidMenifest文件中application节点下添上 android:hardwareAccelerated=”false”以关闭整个应用的硬件加速。
:Picture录的是Canvas中绘制的内容。
方法:
public int getWidth () 获取宽度
public int getHeight () 获取高度
public Canvas beginRecording (int width, int height) 开始录制 (返回一个Canvas,在Canvas中所有的绘制都会存储在Picture中)
public void endRecording () 结束录制
public void draw (Canvas canvas) 将Picture中内容绘制到Canvas中

// 1.创建Picture
private Picture mPicture = new Picture();

---------------------------------------------------------------

// 2.录制内容方法
private void recording() {
    // 开始录制 (接收返回值Canvas)
    Canvas canvas = mPicture.beginRecording(500, 500);
    // 创建一个画笔
    Paint paint = new Paint();
    paint.setColor(Color.BLUE);
    paint.setStyle(Paint.Style.FILL);

    // 在Canvas中具体操作
    // 位移
    canvas.translate(250,250);
    // 绘制一个圆
    canvas.drawCircle(0,0,100,paint);

    mPicture.endRecording();
}

---------------------------------------------------------------

// 3.在使用前调用(我在构造函数中调用了)
  public Canvas3(Context context, AttributeSet attrs) {
    super(context, attrs);

    recording();    // 调用录制
}

(2)drawBitmap
通过BitmapFactory获取
// 第一种
public void drawBitmap (Bitmap bitmap, Matrix matrix, Paint paint)
// 第二种
public void drawBitmap (Bitmap bitmap, float left, float top, Paint paint)
// 第三种
public void drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint)
public void drawBitmap (Bitmap bitmap, Rect src, RectF dst, Paint paint)

3.Path

1.直线方法
(1)moveTo、 setLastPoint、 lineTo 和 close
lineTo (float x, float y):从某个点到参数坐标点之间连一条线
moveTo (float x, float y):只改变下次操作的起点,不影响之前,只影响之后
setLastPoint (float dx, float dy):是重置上一次操作的最后一个点,影响之前的操作也影响之后
close ():close的作用是封闭路径,与连接当前最后一个点和第一个点并不等价。如果连接了最后一个点和第一个点仍然无法形成封闭图形,则close什么 也不做。
(2)addXxx与arcTo
addXXX (…, Path.Direction dir):Direction:CW(顺时针)CCW(逆时针)。指的是path转成点的顺序(ABCD ADCB)
arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)参数说明:
oval 圆弧的外切矩形。
startAngle 开始角度
sweepAngle 扫过角度(-360 <= sweepAngle <360)
forceMoveTo 是否强制使用MoveTo
(3)isEmpty、 isRect、isConvex、 set 和 offset
isEmpty:判断path中是否包含内容。
isRect:判断path是否是一个矩形,如果是一个矩形的话,会将矩形的信息存放进参数rect中。
set:将新的path赋值到现有path。
offset:对path进行一段平移,最后的参数das是存储平移后的path的。
2.贝塞尔曲线
一阶曲线:lineTo(),
二阶曲线:quadTo(),二阶曲线由两个数据点(A 和 C),一个控制点(B)来描述曲线状态
三阶曲线:cubicTo(),三阶曲线由两个数据点(A 和 D),两个控制点(B 和 C)来描述曲线状态
3.其它
(1)rMoveTo, rLineTo, rQuadTo, rCubicTo:rXxx方法的坐标使用的是相对位置(基于当前点的位移),而之前方法的坐标是绝对位置(基于当前坐标系的坐标)。
(2)填充模式:
EVEN_ODD 奇偶规则
INVERSE_EVEN_ODD 反奇偶规则
WINDING 非零环绕数规则
INVERSE_WINDING 反非零环绕数规则
setFillType 设置填充规则
getFillType 获取当前填充规则
isInverseFillType 判断是否是反向(INVERSE)规则
toggleInverseFillType 切换填充规则(即原有规则与反向规则之间相互切换)
(3)布尔操作
boolean op (Path path, Path.Op op)
boolean op (Path path1, Path path2, Path.Op op)
Path.Op. :
DIFFERENCE 差集 Path1中减去Path2后剩下的部分
REVERSE_DIFFERENCE 差集 Path2中减去Path1后剩下的部分
INTERSECT 交集 Path1与Path2相交的部分
UNION 并集 包含全部Path1和Path2
XOR 异或 包含Path1与Path2但不包括两者相交的部分
(4)边界
void computeBounds (RectF bounds, boolean exact)
bounds 测量结果会放入这个矩形
exact 是否精确测量,目前这一个参数作用已经废弃,一般写true即可。
(5)重置路径
重置Path有两个方法,分别是reset和rewind,两者区别主要有一下两点:
方法 是否 是否
reset 保留FillType设置 不保留原有数据结构
rewind 不保留FillType设置 保留原有数据结构
选择权重: FillType > 数据结构
因为“FillType”影响的是显示效果,而“数据结构”影响的是重建速度。
4.PathMeasure
(1):
PathMeasure(): 创建一个空的PathMeasure
PathMeasure(Path path, boolean forceClosed): 创建 PathMeasure 并关联一个指定的Path(Path需要已经创建完成)。
*a:不论 forceClosed 设置为何种状态(true 或者 false), 都不会影响原有Path的状态,即 Path 与 PathMeasure 关联之后,之前的的 Path 不会有任何改变。
*b:forceClosed 的设置状态可能会影响测量结果,如果 Path 未闭合但在与 PathMeasure 关联的时候设置 forceClosed 为 true 时,测量结果可能会比 Path 实际长度稍长一点,获取到到是该 Path 闭合时的状态。
(2):setPath、 isClosed 和 getLength
setPath 是 PathMeasure 与 Path 关联的重要方法,效果和 构造函数 中两个参数的作用是一样的。
isClosed 用于判断 Path 是否闭合,但是如果你在关联 Path 的时候设置 forceClosed 为 true 的话,这个方法的返回值则一定为true。
getLength 用于获取 Path 第一条路径的总长度,在之前的测试中已经用过了。
(3):boolean getSegment (float startD, float stopD, Path dst, boolean startWithMoveTo)
返回值(boolean)- 判断截取是否成功 true 表示截取成功,结果存入dst中,false 截取失败,不会改变dst中内容
startD -开始截取位置距离 Path 起点的长度 取值范围: 0 <= startD < stopD <= Path总长度
stopD -结束截取位置距离 Path 起点的长度 取值范围: 0 <= startD < stopD <= Path总长度
dst -截取的 Path 将会添加到 dst 中 注意: 是添加,而不是替换
startWithMoveTo 起始点是否使用 moveTo 用于保证截取的 Path 第一个点位置不变
(4):nextContour
我们知道 Path 可以由多条曲线构成,但不论是 getLength , getgetSegment 或者是其它方法,都只会在其中第一条线段上运行,而这个 nextContour 就是用于跳转到下一条曲线到方法,如果跳转成功,则返回 true, 如果跳转失败,则返回 false。
(5):getPosTan
boolean getPosTan (float distance, float[] pos, float[] tan)
返回值(boolean) -判断获取是否成功 true表示成功,数据会存入 pos 和 tan 中,
false 表示失败,pos 和 tan 不会改变
distance -距离 Path 起点的长度 取值范围: 0 <= distance <= getLength
pos -该点的坐标值 当前点在画布上的位置,有两个数值,分别为x,y坐标。
tan -该点的正切值 当前点在曲线上的方向,使用 Math.atan2(tan[1], tan[0]) 获取到正切角的弧度值。
(6):getMatrix
boolean getMatrix (float distance, Matrix matrix, int flags)
返回值(boolean) -判断获取是否成功 true表示成功,数据会存入matrix中,false 失败,matrix内容不会改变
distance -距离 Path 起点的长度 取值范围: 0 <= distance <= getLength
matrix -根据 falgs 封装好的matrix 会根据 flags 的设置而存入不同的内容
flags -规定哪些内容会存入到matrix中 可选择
POSITION_MATRIX_FLAG(位置)
ANGENT_MATRIX_FLAG(正切)
(7)Path & SVG
该图片来自这个开源库 ->PathView(https://github.com/geftimov/android-pathview)
SVG 转 Path 的解析可以用这个库 -> AndroidSVG(https://bigbadaboom.github.io/androidsvg/)

你可能感兴趣的:(android开发)