开发艺术探索之View的工作原理

文章按原著的顺序,先介绍所需要的基本概念,然后了解view的三大流程:measure(尺寸)、layout在(位置)、draw(画出来)

  • 基本概念:
    • 了解ViewRoot和DecorView
    • 理解MeasureSpec
    • View的工作流程
  • 自定义View(略)

 

了解ViewRoot和DecorView

推荐阅读:【了解ViewRoot和DecorView】

(个人理解:DecorView是所有view的老大,绘制view先从老大开始;然后ViewRoot是DecorView管理者)

  • ViewRoot
    • ViewRoot对应于ViewRootImpl类,它是连接WindowManager和DecorView的纽带。
    • View的绘制流程通过ViewRoot完成。
    • view的绘制是通过ViewRoot的performTraversals方法开始的:performTraversals()依次调用performMeasure()、performLayout()和performDraw()三个方法,分别完成顶级View的绘制。(方法调用过程:performMeasure()==>measure()==>onMeasure(),onMeasure实现对其所有子元素的measure过程,这样就完成了一次measure过程;接着子元素会重复父容器的measure过程,如此反复至完成整个View树的遍历。layout和draw同理。)
  • DecorView
    • decorView就是viewRoot所提到的顶级View,一般情况下它包含一个LinearLayout,包含一个标题栏titlebar和内容栏content(Activity中setContentView就是这个content)
    • content是一个FrameView,获取方式:ViewGroup content=findViewById(R.android.content)
    • DecorView其实是一个FrameView,view层的事件先经过DecorView,然后再传递给我们的view

理解MeasureSpec

MeasureSpec全称是MeasureSpecification,单词意思是测量规则/测量说明书,通过宽测量值widthMeasureSpec和高测量值heightMeasureSpec决定View的大小。

MeasureSpec是一个32位int值,高2位代表SpecMode(测量模式),低30位代表SpecSize( 某种测量模式下的规格大小)。

  • SpecMode三种模式
    • UNSPECIFIED:父容器不对View有任何限制,要多大有多大。常用于系统内部。
    • EXACTLY(精确模式):父视图为子视图指定一个确切的尺寸SpecSize。对应LyaoutParams中的match_parent具体数值
    • AT_MOST(最大模式):父容器为子视图指定一个最大尺寸SpecSize,View的大小不能大于这个值。对应LayoutParams中的wrap_content。

对于顶级view(也就是DecorView)来说,MeasureSpec由窗口的尺寸和自身的LayoutParams共同确定;对于普通的view,MeasureSpec由父容器的MeasureSpec和自身的LayoutParams共同确定;

view的工作流程

工作流程:measure(测量尺寸)==>layout(位置)==>draw绘制

  • onMeasure()方法:确定View的测量宽高
  • onLayout()方法:确定View的最终宽高和四个顶点的位置
  • onDraw()方法:将View 绘制到屏幕上

measure过程

view的measure过程:通过measure方法就能完成测量

ViewGroup的measure:除了完成ViewGroup自身的测量外,还会遍历去调用所有子元素的measure方法。(ViewGroup中没有重写onMeasure(),而是提供measureChildren()。)

layout过程

layout 作用是ViewGroup来确定子元素四个顶点的位置,当ViewGroup位置确定后,会在onLayout中遍历所有的子元素,并调用layout方法,layout方法中onLayout方法又会被调用。

推荐阅读:【自定义View Draw过程】

draw过程

  • 绘制背景:background.draw(canvas)
  • 绘制自己:onDraw(canvas)
  • 绘制children:dispatchDraw(canvas)     (dispatchDraw遍历所有的子元素的draw方法,进而实现子元素的draw过程)
  • 绘制装饰:onDrawScrollBars(canvas)

推荐阅读:【对View工作流程的理解(源码)】

自定义view

四类不同层次的自定义view

  • 继承View重写onDraw方法(主要实现一些不规则的效果。重写onDraw方法需要自己支持wrap_content,并且padding也需要自己处理)
  • 继承ViewGroup派生的特殊的Layout(用于实现自定义的布局,需要合适地处理ViewGrou的测量、布局这个过程,并实现处理子元素的测量和布局过程)
  • 继承特定的View(常见,一般用于扩展某种已有的View功能。不需要自己支持wrap_content和padding等)
  • 继承特定的ViewGroup(如LinearLayout)

自定义View须知

  • 让View支持wrap_content(如果不在onMeasure中处理,当外界再不聚中使用wrap_content时就无法达到预期的效果)
  • 如有必要,让View支持padding(如果直接继承View,不在draw中处理padding,那么padding属性是无法起作用的,等等)
  • 尽量不要在View中使用Handler(没必要,因为view内部本身提供了post系列的方法,完全可以代替Handler的作用)
  • View中如果有线程或者动画,需要及时停止(view变得不可见时,需要及时停止线程和动画,不及时处理的话可能造成内存泄漏)
  • View带有滑动嵌套时,需要处理好滑动冲突(否则会严重影响view的效果)

.(略,待功力深厚再来与之一战!)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值