View绘制过程及原理

     View的绘制过程就是从ViewRoot的performTraversals方法开始的,它先后经过measurelayoutdraw三个过程才能最终将一个View绘制出来。分别对应onMeasure()、onLayout()和onDraw()这三个方法。下面分别谈一下这三个方法。

measure

    measure是用来测量view的宽和高。在measure方法中又会调用onMeasure方法,在onMeasure方法中会对所有的子元素进行measure过程,这个时候measure流程就从父容器传递到子元素中了

《View绘制过程及原理》

measure()方法接收两个参数,widthMeasureSpec和heightMeasureSpec,这两个值分别用于确定视图的宽度和高度的测量规格。MeasureSpec代表一个32的int值,高2位代表SpecMode测量模式,低30位代表SpecSize测量规格大小。SpecMode 分为三类

  1.EXACTLY(完全)

    父容器完全决定view的大小,子view的大小被忽略,被限定在给定的边界里。

  2.AT_MOST(至多)

    子view最多达到给定大小的值

  3.UNSPECIFIED(未指定)

    父容器不对view的大小做任何限制,子view可以得到任意想要的大小

  在setMeasuredDimension()方法调用之后,我们才能使用getMeasuredWidth()和getMeasuredHeight()来获取视图测量出的宽高,以此之前调用这两个方法得到的值都会是0。

layout

  layout方法是在measure方法结束后进行,此时view的大小已经测量好了。layout的作用是ViewGroup用来确定子元素的位置,当ViewGroup的位置被确定后,它在onLayout中会遍历所有的子元素并调用Layout方法,在layout方法中onLayout方法又会被调用。这样一层一层的完成所有子View的布局过程。layout里面通过setFrame来确定View的四个顶点的位置,然后再layout中调用onLayout,这个方法用来确定子View的位置,起到一层层传递的作用。

draw

  draw方法是在layout方法结束后进行,顾名思义,这里是绘制view的地方。draw主要分为6步。

  1.绘制view的背景图

  2.如果要视图显示渐变框,开始准备

  3.调用onDraw()函数,绘制视图本身。在view中进入onDraw()方法会发现是个空方法,因为每个子类视图的内容部分都是各不相同的,所以需要在子类中去重载,自己绘制

  4.绘制子视图,调用dispatchDraw()。如果视图中没有子视图,就不需要绘制了。因此你会发现View中的dispatchDraw()方法又是一个空方法,而ViewGroup的dispatchDraw()方法中就会有具体的绘制代码

  5.如果要视图显示渐变框,这里开始绘制

  6.绘制滚动条

 显然 第2和第5步基本是用不到的。重要的是第3步。

    原文作者:lucifer121
    原文地址: https://www.jianshu.com/p/2558d78dc619
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞