自定义View学习笔记1

一:坐标

1. View的坐标系:                                                                                  2. motionEvent中的方法

                                           

二:角度和弧度

为了准确描述一个角的大小,引入了角度和弧度(角度和弧度的进制是不一样的,角度60进制、弧度是10进制)

定义:

1. 角度- 俩条射线从圆心射出,形成一个夹角和夹角正对的一段弧当这段弧长正好=圆周长1/360俩条射线的夹角的大小为1度

2. 弧度- 俩条射线从圆心射出,形成一个夹角和夹角正对的一段弧当这段弧长=圆的半径俩条射线的夹角大小为1弧度

换算:

圆一周对应的角度deg是360度,对应的弧度rad换算2π弧度==>

    rad = deg x π / 180            deg = rad x180/π

注意:

屏幕默认坐标系下,角度的增大方向是顺时针(而在数学中角度的增大是逆时针)

三:颜色

支持的颜色(字母 - 通道类型、 数值 - 该类型用多少位二进制描述):

ARGB8888(四通道高精度32位)

ARGB4444(四通道低精度16位)

RGB565(屏幕默认模式16位)

Alpha8(仅有透明通道8位)

说明(RGB全取最小值:黑色、 RGB全取最大值:白色):

A-Alpha:透明度(0 - 255   透明 - 不透明)

R-Red:红色(0 - 255    无色 - 红色)

G-Green:绿色(0 - 255    无色 - 绿色)

B-Blue:蓝色(0 - 255    无色 - 蓝色)

创建和使用:

int color = Color.GRAY;//灰色

int color = Color.argb(127,255,0,0);//半透明红色

取色工具介绍:

1. ColorPix下载地址(针对win)https://www.colorschemer.com/

2. Picpick下载地址(针对Win)https://picpick.app/zh/

3. Sip下载地址(针对Mac)https://apps.apple.com/us/app/sip/id507257563?mt=12

说明:

因为显示屏是无法透明的,所以最终显示在屏幕上的颜色可以认为没有Alpha通道

Alpha通道主要是用来俩个图像混合的时候生效

混合模式计算:

    (RGB通道)最终颜色 = 绘制颜色+(1-绘制颜色透明度) x  Canvas上的原有颜色

四: 绘制流程

说明:

1. 自定义ViewGroup:

    利用现有组件根据特定布局方式来组成新的组件(大多继承ViewGroup和Layout,包含有子View)

2. 自定义View:

     自己实现需要的功能,一般继承自View、SurfaceView或其他的View,不包含子View

     注: 2.1 自定义View在大多数情况下都有替代方案,利用图片或组合动画来实现

             2.2 使用图片和组合动画可能会面临内存耗费过大,制作麻烦等问题    

函数说明:

1. 构造函数:初始化一些内容和获取自定义属性(自定义属性参数:AttributeSet)

2. 测量View大小(onMeasure):

    参数widthMeasureSpec和heightMeasureSpec:宽高和各自方向上对应的测量模式来合成的一个值

    View的大小不仅由自身决定,同时也会受到父控件影响,所以为了适应各种情况,一般会自己进行测量,在该方法中可以取到宽高的确切数值和测量模式(MeasureSpec     getSize/getMode)

    测量模式在MeasureSpec中:

          UNSPECIFIED(0)--- 默认值,父控件没有给子View任何限制,子View可以设置为任意大小

           EXACTLY((1) --- 父控件确切指定了子View的大小

           AT_MOST(2) --- 子View具体大小没有尺寸限制,但是存在上限,上限一般为父View大小

    对于View宽高进行修改:使用setMeasuredDimension(widthsize,heightsize)

3. 确定View大小(onSizeChanged):

    视图大小发生改变时调用

4. 确定子View的布局位置(onLayout):

     在自定义ViewGroup中会使用到,使用子view的layout(了,他,人,b)设置子View的位置

5. 绘制内容(onDraw):

6. 自定义完之后会暴露一席接口对View进行监听或者获取状态等其他属性

五:Canvas绘制图形

1. 常用操作(通过canvas对象调用)

     1.1 绘制颜色(使用单一颜色填充整个画布):drawColor、drawRGB、drawARGB

           canvas.drawColor(Color.BLUE); //绘制蓝色

     1.2 绘制形状(点、线、矩形、圆角矩形、椭圆、圆、圆弧):drawPoint、drawPoints、drawLine、drawLines、drawRect、drawRoundRect、drawOval、drawCircle、drawArc

           canvas.drawPoint(200, 200, mPaint); //在坐标(200,200)位置绘制一个点

           canvas.drawPoints(new float[]{ //绘制一组点,坐标位置由float数组指定 500,500, 500,600, 500,700 },mPaint);

           canvas.drawLine(300,300,500,600,mPaint); // 在坐标(300,300)(500,600)之间绘制一条直线

           canvas.drawLines(new float[]{ 100,200,200,200, 100,300,200,300 },mPaint);// 绘制一组线 每四数字(两个点的坐标)确定一条线

        绘制矩阵:

         // 第一种 canvas.drawRect(100,100,800,400,mPaint);

         // 第二种 Rect rect = new Rect(100,100,800,400);

                        canvas.drawRect(rect,mPaint);

          // 第三种 RectF rectF = new RectF(100,100,800,400);

                        canvas.drawRect(rectF,mPaint);

        绘制圆角矩阵:绘制Rect和RectF: 精度不同,int型和float型

         // 第一种 RectF rectF = new RectF(100,100,800,400); canvas.drawRoundRect(rectF,30,30,mPaint);

         // 第二种 canvas.drawRoundRect(100,100,800,400,30,30,mPaint);

         俩个30代表的意义:

         绘制椭圆

         // 第一种 RectF rectF = new RectF(100,100,800,400); canvas.drawOval(rectF,mPaint);

         // 第二种 canvas.drawOval(100,100,800,400,mPaint);

           绘制圆:canvas.drawCircle(500,500,400,mPaint); 绘制一个圆心坐标在(500,500),半径为400 的圆

          绘制圆弧  

          // 第一种 public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint){}

        // 第二种 public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint) {}

     1.3 绘制图片 (绘制位图和图片):drawBitmap、drawPicture

     1.4 绘制文本(绘制文字、绘制指定位置文字、根据路径绘制文字):drawText、drawPostText、drawTextOnPath

     1.5 绘制路径(绘制路径和贝塞尔曲线):drawPath

     1.6 顶点操作(通过对顶点操作可以使图像变形):drawVertices -- 直接对画布作用、drawBitmapMesh -- 只对绘制的bitmap作用

     1.7 画布裁剪(设置画布的显示区域):clipPath、clicpRect

     1.8 画布快照(保存当前状态、回滚到上次保存状态、保存图层状态、回滚到指定状态、获取保存次数):save、restore、saveLayerXxx、restoreToCount、getSaveCount

     1.9 画布变换(位移、缩放、旋转、错切):translate、scale/rotate、skew

     2.0 Matrix矩阵(实际上画布的位移、缩放等操作的都是图像矩阵Matrix):getMatrix、setMatrix、councat

2. Paint

     2.1 画笔模式:mPaint.setStyle(Paint.style.FILL):描边-STROKE 、 填充 - FILL 、 描边加填充FILL_AND_STROKE

六:Canvas

说明:所有画布操作只影响后续的绘制,对之前已经绘制过的内容没有影响

1. 位移translate:是坐标系的移动,可以为图形绘制一个合适的坐标系(位移是基于当前位置)

2. 缩放scale:缩放比例 / 缩放比例 + 缩放位置

    缩放比例取值范围说明:

3. 旋转rotate:旋转角度和旋转中心点

4. 错切skew(特殊类型的线性变换):俩个参数在X轴方向倾斜角度、在Y轴方向倾斜角度

5. 快照和回滚

画布是由多个图层构成的

saveFlags:

七:绘制bitmap

1. 从不同位置获取bitmap

    资源文件:BitmapFactory.decodeResource(context.getResources(),R.raw.bimmap)

    assets下:

      

 内存卡:BitmapFactory.decodeFile("/sdcard/bitmap.png");

 网络文件:BitmapFactory.decodeStream(is)     

2. 绘制bitmap                

    

   第三种俩个参数:src指定绘制区域、dst指定图片在屏幕上显示区域

 八:Path路径在canvas中使用 1.

1. 注意:

    关闭硬件加速,以免引起其他问题:android:hardwareAccelerated=”false”

2. 区分:

    封闭路径:首尾相接形成封闭区域

    开放路径:没有首尾形成封闭区域

3. 方法使用详解

    第1组: moveTo、 setLastPoint、 lineTo 和 close

    准备画笔paint

     lineTo: 添加上一个点到当前点之间的直线path(上一次没有操作默认为坐标原点)

     moveTo:移动(改变)下一次操作的起始位置(改变下次位置不影响之前的路径)

     setLastPoint:重置当前path最后点的位置(绘制前调用和moveTo效果一样)会影响之前绘制的路径

     close: 连接第一个点到最后一个点,形成闭合路线

    第2组: addXxx与arcTo

       圆形 public void addCircle (float x, float y, float radius, Path.Direction dir)

       椭圆 public void addOval (RectF oval, Path.Direction dir)

       矩形 public void addRect (float left, float top, float right, float bottom, Path.Direction dir)

               public void addRect (RectF rect, Path.Direction dir)

       圆角矩形 public void addRoundRect (RectF rect, float[] radii, Path.Direction dir)

                      public void addRoundRect (RectF rect, float rx, float ry, Path.Direction dir)

       Direction参数说明:方向、趋势(顺时针 - CW、逆时针 - CCW)

       绘制矩阵 

        

         参数说明:

                           

         区别:

                        addArc和arcTo     

    第3组:isEmpty、 isRect、isConvex、 set 和 offset

                 isEmpty:判断path是否为空

                 isRect:判断path是否是一个矩阵

                  set: 用新的路径替换当前路径所有内容

                  offset: 对当前路径之前的操作进行偏移(不会影响之后的操作)

   例:

    结果:

   其他方法

     quadTo/cubicTo: 分别为二次和三次贝塞尔曲线的方法

      rMoveTo/rLineTo/rQuadTo/rCubicTo: 基于当前点坐标系(偏移量)

      setFillType/getFillType/isInverseFillType/toggleInverseFillType:设置、获取、判断和切换填充模式

      incReserve:提示path还有多少个点等待加入

      op:对俩个path进行布尔运算

      computeBounds: 计算path边界

      reset/rewind:清除path中的内容(reset - 不保留内部数据结构,保留fillType、rewind - 保留内部数据结构,不保留fillType)

      transform: 矩阵变换

九:贝塞尔曲线

    贝塞尔曲线是一系列点来控制曲线状态(数据点: 确定曲线起始和结束位置、控制点:确定曲线弯曲程度)

   原理:

        一阶曲线原理:仅有A和B俩个数据点,最终形成一个线段(其实就是lineTo)

        二阶曲线原理:数据点A和C,控制点B(其实就是quadTo)

        三阶曲线原理:数据点A和D,控制点B和C(其实就是cubicTo)

十:path中的布尔运算

      运算的5中逻辑

       

      重置路径:fillType影响的是显示效果、数据结构影响的是重建速度

PathMeasure是用来测试Path的类

1. 构造方法:创建PathMeasure并关联一个指定的path(path需要已经创建完成)

2. 公共方法:

     2.1 关联一个path:setPath(Path path,boolean forceClosed)

     2.2 是否闭合:isClosed()

     2.3 获取Path的长度:getLength()

     2.4 跳转到下一个轮廓(曲线):nextContour()

     2.5 截取片段:getSegment(float startD,float stopD,Path dst,boolean startWithMoveTo)

            参数:(1. startD和stopD不在取值范围内同时,俩个值不相同,不会改变dst内容

                           2. 4.4及之前版本,开启硬件加速,在更改dst内容后可能绘制会出现问题)

                     开始截取位置距离path起点的长度(范围:0 <= startD <stopD<.path总长度)

                     结束截取位置距离path起点的长度(范围:0<=startD<stopD<=path总长度)

                     截取的path将会添加到dst中

                     起始点是否使用moveTo(true:保证截取到的path片段不会发生变形 false:保证存储截取片段的path的连续性)

            返回值:判断截取是否成功

     2.6 获取指定长度的位置坐标及该点切线值:getPosTan(float distance,float[] pos,float[] tan)

           返回值:判断是否成功(成功 - 数据会存入pos和tan中、失败 - pos和tan不会改变)

           参数:distance距离path起点的长度(范围:0<= distance<=getLehgth)

                      pos该点的坐标值(当前点在画布上的位置)

                      tan该点的正切值(当前点在曲线上的方向,使用Math.atan2(tan[1],tan[0])获取到正切角的弧度值)

           要点:通过tan的值计算出图片旋转的角度(tan[0]是邻边边长、tan[1]对边边长)

                      通过matrix来设置图片对旋转角度和位移

                      页面刷新(使用线程或者ValueAnimator来控制界面的刷新)

     2.7 获取指定长度的位置坐标及改点Matrix:getMatrix(float distance,Matrix matrix,int flags)

           返回值:判断获取是否成功

           参数:distance - 距离path起点长度(范围:0<. distance<=getLehgth)

                      matrix - 根据flags封装好的matrix(会根据flags的设置而存入不同的内容)

                      flags - 规定哪些内容会存入到matrix中(位置:POSITION_MATRIX_FLAG、正切:ANGENT_MATRIX_FLAG)

说明:关联之后的path内容进行了更改,则需要使用setPath方法冲洗关联

           构造方法第二个参数forceClosed:不论设置为何种状态,都不会影响原有path的状态(path与pathMeature关联之后,之前的path不会有任何改变)

            forceClosed设置状态可能会影响测量结果(path未闭合,关联时候forceClosed为true,测量结果比path实际长度稍长,获取到的是闭合状态)

十一:SVG

 定义:是一种矢量图,内部用的是xml格式化存储方式存储着操作和数据(SVG看作的path的各项操作简化书写后的存储格式)

十二:Matrix

 1. 缩放:

  2. 错切:水平

                  垂直 

                  覆合

    3. 旋转:

    4. 平移:

    5. 基本方法

         equals:比较俩个matrix数值是否相同

         hashCode:获取哈希值

         toString:转换成字符串

         toSortString:转换成短字符串

     6. 数值操作

         set(Matrix src):将参数值复制到当前matrix中,如果参数为空则重置当前matrix

         reset:重置当前matrix

         setValues(float[] values):长度需要大于9,拷贝数组中的前9位数值赋值给当前matris

         getValues(float[] values):与setValues是一对,长度需要>9,将matrix中的数值拷贝到参数的前9位中

     注意:

              1. 在canvas中获取到的matrix并不是初始矩阵,而是经过偏移后的矩阵,偏移的距离就是距离屏幕左上角的位置

                   * 可以用来判定View在屏幕上的绝对位置,View可以根据所处位置做出调整

              2. 构造Matrix时使用的是矩阵乘法,前乘和后乘结果差别很大

              3. 受矩阵乘法影响,后面的执行操作可能会影响到之前的操作(使用时需要注意构造顺序)

   7. setPolyToPoly中最后一个参数pointCount取值范围0-4

        pointCount = 0:就是执行了reset

        pointCount = 1: 就是执行了translate

        pointCount = 2:进行缩放、旋转、平移变换

        pointCount = 3:进行缩放、旋转、平移、错切变换

        pointCount = 4:进行缩放、旋转、平移、错切以及任何变形

       使用该方法可以制作3D效果:

  8. setRectToRect最后一个参数Matrix.ScaleToFit(缩放适配模式)

        CENTER:居中(对src等比例缩放,居中放在dst中)

        START: 顶部(等比例缩放,放置在dst左上角)

        END: 底部(等比例缩放,放置在dst右下角)

        FILL:充满(拉伸宽和高,完全填满dst)

  9. rectStaysRect判断矩形经过变形后是否任Wie矩形(mapRect方法返回值就是根据该方法来判断的)

  10. setSinCos,控制Matrix旋转的,并不常用,因为Matrix已经封装好了rotate

十三:Matrix Camera

camera主要作用是将3D效果在2D平面的投影,实际该类更像是操作Matrix的工具类

 1. 方法:

     基本方法:保存当前状态save、回滚到上一次保存状态restore

     常用方法:计算当前状态下矩阵对应的状态,将计算后的矩阵值赋值给参数matrix:getMatrix(Matrix matrix)

                                                                                                      应用到指定的canvas上:appliToCanvas(Canvas)

      平移:沿X轴平移   (平移方向和平移距离一致)

                 沿Y轴平移(两者y轴相反,所以camera.translate(0,-y,0); 与 matrix.postTranslate(0,y);平移方向和距离一致:向下移动Y个单位)

                 沿Z轴平移:View与camera在同一条直线上(近大远小)

                                      不在同一条直线上(近大远离屏幕投影位置、远小接近屏幕投影位置)

                                        

           旋转:沿X、Y、Z轴旋转  

                      旋转中心默认是坐标原点,对于图片来说是左上角位置,3D无法没有默认只想中心位置,所以操作如下:

                      

                      处理翻转导致的失真变形以及图片太大无法显示(操作的是MPERSP_0和MPERSP_1):

                     

                      修改代码:

                        

                        

          相机位置:

                            可以使用translate和ratate来控制拍摄对象

                            注意:View与camera的Z轴距离不能为0

                                       camera右移 == View左移(单位不同:camera平移1 == view平移72像素)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值