企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 自定义View > 参考文章:[http://www.gcssloop.com/customview/CustomViewIndex/  ](http://www.gcssloop.com/customview/CustomViewIndex/ "http://www.gcssloop.com/customview/CustomViewIndex/  ") ### 1、坐标系 * **Android View中的y轴正方向是向下的** * **View的坐标系是相对于父控件而言的** ``` getTop(); //获取子View左上角距父View顶部的距离 getLeft(); //获取子View左上角距父View左侧的距离 getBottom(); //获取子View右下角距父View顶部的距离 getRight(); //获取子View右下角距父View左侧的距离 ``` * MotionEvent中getX( )和getRawX( )的区别 getX( )获取的是相对于父控件的 getRawX( ) 获取的是相对于屏幕默认的坐标轴 ![image.png](https://upload-images.jianshu.io/upload_images/13971762-235a13f4720ede7c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ### 2、自定义View的流程 ![自定义View的流程.png](https://upload-images.jianshu.io/upload_images/13971762-092f1f8bec8128d4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) | 操作类型 | 相关API | 备注 | |--|--|--| | 操作类型 | 相关API | 备注 | | 绘制颜色 | drawColor, drawRGB, drawARGB | 使用单一颜色填充整个画布 | | 绘制基本形状 | drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc | 依次为 点、线、矩形、圆角矩形、椭圆、圆、圆弧| | 绘制图片 | drawBitmap, drawPicture | 绘制位图和图片 | | 绘制文本 | drawText, drawPosText, drawTextOnPath | 依次为 绘制文字、绘制文字时指定每个文字位置、根据路径绘制文字 | | 绘制路径 | drawPath | 绘制路径,绘制贝塞尔曲线时也需要用到该函数| | 顶点操作 | drawVertices, drawBitmapMesh | 通过对顶点操作可以使图像形变,drawVertices直接对画布作用、drawBitmapMesh只对绘制的Bitmap作用| | 画布剪裁 | clipPath, clipRect | 设置画布的显示区域 | | 画布快照 | save, restore, saveLayerXxx, restoreToCount, getSaveCount | 依次为 保存当前状态、 回滚到上一次保存的状态、 保存图层状态、 回滚到指定状态、 获取保存次数 | | 画布变换 | translate, scale, rotate, skew | 依次为 位移、缩放、 旋转、错切| | Matrix(矩阵) | getMatrix, setMatrix, concat | 实际上画布的位移,缩放等操作的都是图像矩阵Matrix, 只不过Matrix比较难以理解和使用,故封装了一些常用的方法。 | ### 3、View 的save和restore | **相关API** | 简介 | |--|--| | save | 把当前的画布的状态进行保存,然后放入特定的栈中 | | saveLayerXxx | 新建一个图层,并放入特定的栈中 | | restore | 把栈中最顶层的画布状态取出来,并按照这个状态恢复当前的画布 | | restoreToCount | 弹出指定位置及其以上所有的状态,并按照指定位置的状态进行恢复| | getSaveCount | 获取栈中内容的数量(即保存次数)| ![layer.png](https://upload-images.jianshu.io/upload_images/13971762-cb9518064cd7548c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ``` // save 使用 // 保存全部状态 public int save () // 根据saveFlags参数保存一部分状态 public int save (int saveFlags) saveFlags: // ALL_SAVE_FLAG 默认,保存全部状态 // CLIP_SAVE_FLAG 保存剪辑区 // CLIP_TO_LAYER_SAVE_FLAG 剪裁区作为图层保存 // FULL_COLOR_LAYER_SAVE_FLAG 保存图层的全部色彩通道 // HAS_ALPHA_LAYER_SAVE_FLAG 保存图层的alpha(不透明度)通道 // MATRIX_SAVE_FLAG 保存Matrix信息( translate, rotate, scale, skew) ``` ``` // saveLayer使用 // 无图层alpha(不透明度)通道 public int saveLayer (RectF bounds, Paint paint) public int saveLayer (RectF bounds, Paint paint, int saveFlags) public int saveLayer (float left, float top, float right, float bottom, Paint paint) public int saveLayer (float left, float top, float right, float bottom, Paint paint, int saveFlags) // 有图层alpha(不透明度)通道 public int saveLayerAlpha (RectF bounds, int alpha) public int saveLayerAlpha (RectF bounds, int alpha, int saveFlags) public int saveLayerAlpha (float left, float top, float right, float bottom, int alpha) public int saveLayerAlpha (float left, float top, float right, float bottom, int alpha, int saveFlags) ``` > **saveLayerXxx方法会让你花费更多的时间去渲染图像(图层多了相互之间叠加会导致计算量成倍增长),使用前请谨慎,如果可能,尽量避免使用。使用saveLayerXxx方法,也会将图层状态也放入状态栈中,同样使用restore方法进行恢复** ##### restore 状态回滚,就是从栈顶取出一个状态然后根据内容进行恢复。 同样以上面状态栈图片为例,调用一次restore方法则将状态栈中第5次取出,根据里面保存的状态进行状态恢复。 ##### restoreToCount 弹出指定位置以及以上所有状态,并根据指定位置状态进行恢复。 以上面状态栈图片为例,如果调用restoreToCount(2) 则会弹出 2 3 4 5 的状态,并根据第2次保存的状态进行恢复。 ##### getSaveCount 获取保存的次数,即状态栈中保存状态的数量,以上面状态栈图片为例,使用该函数的返回值为5。不过,**该函数的最小返回值为1**,即使弹出了所有的状态,返回值依旧为1,代表默认状态。 ### 4、常用操作、方法 ``` canvas.translate(mWidth / 2, mHeight / 2); // 移动坐标系到屏幕中心 canvas.scale(1,-1); // 翻转y坐标轴 ``` > ***@param forceMoveTo** If true, always begin a new contour with the arc* > > *// 默认值为false,默认使用lineTo连接到**画圆弧前的最后那个点**;如果为true,则强制移动到**画圆弧前的最后那个点。*** > > **public void** arcTo(RectF oval, **float** startAngle, **float** sweepAngle,**boolean** forceMoveTo) ``` // 判断path是否是一个矩形,如果是一个矩形的话,会将矩形的信息存放进参数rect中。 public boolean isRect (RectF rect) //eg path.lineTo(0,400); path.lineTo(400,400); path.lineTo(400,0); path.lineTo(0,0); RectF rect = new RectF(); boolean b = path.isRect(rect); Log.e("Rect","isRect:"+b+"| left:"+rect.left+"| top:"+rect.top+"| right:"+rect.right+"| bottom:"+rect.bottom); ``` > com.sloop.canvas E/Rect: isRect:true| left:0.0| top:0.0| right:400.0| bottom:400.0 # 动画 > 参考:[https://github.com/OCNYang/Android-Animation-Set](https://github.com/OCNYang/Android-Animation-Set "https://github.com/OCNYang/Android-Animation-Set") > > [https://blog.csdn.net/yanbober/article/details/46481171](https://blog.csdn.net/yanbober/article/details/46481171 "https://blog.csdn.net/yanbober/article/details/46481171")[](https://github.com/OCNYang/Android-Animation-Set)