自定义View相关

activitythread里面的resume,
获取 WindowManager(桥接模式,核心方法不想暴露出来,用一个中间类持有核心类成员,中间类类可以访问核心类方法暴露给用户调用),
用wm. addview方法
通过viewRootImpl添加decorView
并开始调用requestLayout开始请求布局
requestLayout会检测当前线程是否在主线程,所以view更新ui要在onResume之前完成
requestlayout通过handler发送消息去遍历viewTree

requestLayout会重新刷新 测量,布局,绘制。但是只有当view以及子view的位置或大小发生变化的时候才会执行绘制。
invalidate只会在UI线程调用绘制方法,postInvalidate可以在非UI线程中调用

MeasureSpec是32位,前2位是模式(match_parent,wrap_content),后30位是容器的大小值
unspecified:父view不对子view有任何限制,子view需要多大就有多大。
exactly:父View已经测量出子view所需要的精确大小,这个时候view的最终大小就是SpecSize所值的职位,对应于match_parent和精确值两种。
at_most:子view的最终大小是父View指定的SpecSize值,并且子View的大小不能大于这个值,对应于wrap_content这种模式。
测量一步一步往子view去测量,根据子view的大小确定父容器的宽高,例如specMode为unspecified,该view的大小由于specSize决定。如果为at_most,那么会一步一步往子view测量计算宽高,如果不超过specSize,那么就是这次测量的宽高,如果超过了specSize,那么就是specSize的值。

MeasureSpec的数值来源,DecorView由窗口的尺寸和其自身的LayoutParams共同来决定,普通view由父容器和自身的Layoutparams共同来决定。

=================onDraw里面涉及到的知识=================

图形绘制画笔Paint

Paint主要有渲染、滤镜、Xfermode等重要知识要了解

渲染

Shader:着色器

  • Canvas的drawXXXX画具体形状,Paint的shader定义的就是图形的着色和外观。
  • TileMode:拉升形式
    1.CLAMP:是拉升最后一个像素铺满
    2.REPEAT:类似电脑壁纸,横向纵向不足的重复放置
    3.MIRROR:在横向纵向不足处不断翻转镜像平铺

BitmapShader:位图渲染

  • 用BitMap对绘制的图形进行渲染着色,简单来说是用图片对图形进行贴图。(圆形头像、放大镜效果)

LinearGradient: 线性渲染

  • 用于图形元素的填充或描边。(歌词显示)

SweepGradient: 扫描渲染

RadialGradient: 环形渲染

ComposeShader: 组合渲染

滤镜

对原有图像色彩进行调整

  • 颜色模式:是将某种颜色表现为数字形式的模型,或者说是一种记录图像颜色的方式。
    主要分为RGB模式、CMYK模式、HSB模式、LAB颜色模式、位图模式、灰度模式、索引颜色模式、双色调模式和多通道模式
  • 颜色通道:
    一个像素的颜色由四个分量组成,其中A为透明通道、R为红色通道、G为绿色通道、B为蓝色通道。像素点通道值越大像素点所占颜色比列越多。
  • 颜色矩阵
    通过矩阵与矩阵的相乘等运算从而改变矩阵值


    image.png
  • setMaskFilter设置滤镜
    1.BlurMaskFilter模糊遮罩滤镜
    2.EmbossMaskFilter浮雕遮罩滤镜;绘制的图像感觉像是从屏幕中“凸”起来更有立体感一样(在设计软件中类似的效果称之为斜面浮雕)
    **硬件加速会看不到效果,所以需要关闭硬件加速

Xfermode

通过使用Xfermode能够完成图像组合的效果(通过两张图的组合生成一张图)

Canvas

字面翻译“画布”,本质其实是一个绘制图形的工具

坐标体系:默认零点位于屏幕左上角

  • 画图分析:两种坐标系:
    1.canvas坐标系(最外层画板,一经确定就不会改变)
    2.绘图坐标系:修改坐标后不可逆。
  • 主要方法
    1.Canvas.save() ,保存画布,将所有已经绘制的图像保存起来,让后续的操作就像在新得图层上面操作一样。
    2.Canvas.restore(),合并图层操作,将save()之后绘制的所有图像与save()之间的图像进行合并。
    3.Canvas.translate(),绘图坐标的平移。
    4.Canvas.rotare(),绘制图标的翻转。
    5.运算方式,Matrix变换矩阵

图层概念

  • 状态栈:save、restore方法来保存和还原变换操作Matrix以及Clip裁剪,也可以通过restoretoCount直接还原到对应的保存状态。
  • layer栈:saveLayer的时候都会新建一个透明的图层(离屏Bitmap-离屏缓冲),并且会将saveLayer之前的一些Canvas操作延续过来,后续的绘图操作都在新建的layer上面进行,当我们调用restore或者restoreToCount时,更新到对应的图层和画布上。
    image.png

PathMeasure获取path相关属性负责类,轨迹动画使用

view的事件分发机制

1 整体流程
linux/设备 -> 推送消息 -> dev/input(文件系统) ->
InputManager(EventHub -> 信息加工 -> inputReaderThread -> 事件传递 -> InputDispatcherThread)-> (socketpair)-> ViewRootImpl -> JNI -> IMS -> WMS

  • 事件分发涉及到onTouch,onTouchEvent,onClick事件,onTouch返回为true的话onClick就不会收到回调
  • 事件分发涉及到两个方法,一个dispatchTouchEvent,一个onInterceptTouchEvent,一个分发一个拦截。
    dispatchTouchEvent发送事件,由onInterceptTouchEvent确认是否拦截,true则拦截自己处理onTouchEvent事件,fasle则不拦截让他继续发送事件。拦截后生成一条tag链路,以后事件只发送给这条链路
  • dispatchTouchEvent从activity->phoneWindow->DecorView->viewGroup->view。相应的如果需要拦截则处理onInterceptTouchEvent返回事件,注意view中没有onInterceptTouchEvent方法。
  • 我们处理滑动冲突事件一般会遇到两种情况,一种同向滑动,一种非同向滑动,同向滑动可能需要用到behave处理。非同向滑动则需要我们根据相应的角度去处理滑动冲突事件。
  • 滑动冲突事件根据滑动角度确认是否拦截,主要处理方案有两种,一种外部拦截,一种内部拦截。
    外部拦截相对简单一些,就是外层view直接重写onInterceptTouchEvent,然后根据事件的角度确认是否需要拦截。
  • 某些情况下外部拦截无法处理的时候需要使用内部拦截,内部拦截就是子容器发送事件给父容器getParent.requestDisallowInterceptTouchEventb不要拦截,我来处理。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容