Android中View的绘制过程

View可以看成一个树形结构,父控件是父节点,子控件是子节点。View的绘制过程就是遍历这棵树。

View的绘制有三步:

measure:测量View的Width和Height, layout:布局View(left,right,top,bottom),指定View和手机屏幕的上下左右的距离。 draw:绘图

以上的步骤必须按照顺序来。(顺便说一下,以上三个步骤发生在View的构造方法之后。)

一、measure

measure是绘制视图的第一步,因为只有知道的View的大小(Width和Height)才能绘图。

我们在编写layout的xml文件的时候,会遇到layout_width和layout_height两个属性,对于这两个属性我们有三个选择:fill_parent、wrap_content和具体值,measure就是用来处理fill_parent、wrap_content两个属性的,在绘图的时候,要知道具体的值,所以要计算fill_parent、wrap_content的具体值。

下面是几个重要的函数和参数:

public final void measure(int widthMeasureSpec, int heightMeasureSpec) protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed)

前两个方法是View类里面的方法,后三个方法是ViewGroup类里面的方法。

先来看看measure的源码:

/**       * <p>       * This is called to find out how big a view should be. The parent       * supplies constraint information in the width and height parameters.       * </p>       *       * <p>       * The actual mesurement work of a view is performed in       * {@link #onMeasure(int, int)}, called by this method. Therefore, only       * {@link #onMeasure(int, int)} can and must be overriden by subclasses.       * </p>       *       *       * @param widthMeasureSpec Horizontal space requirements as imposed by the       *        parent       * @param heightMeasureSpec Vertical space requirements as imposed by the       *        parent       *       * @see #onMeasure(int, int)       */       public final void measure(int widthMeasureSpec, int heightMeasureSpec) {           if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||                   widthMeasureSpec != mOldWidthMeasureSpec ||                   heightMeasureSpec != mOldHeightMeasureSpec) {                  // first clears the measured dimension flag                mPrivateFlags &= ~MEASURED_DIMENSION_SET;                  if (ViewDebug.TRACE_HIERARCHY) {                   ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);               }                  // measure ourselves, this should set the measured dimension flag back                onMeasure(widthMeasureSpec, heightMeasureSpec);                  // flag not set, setMeasuredDimension() was not invoked, we raise                // an exception to warn the developer                if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {                   throw new IllegalStateException("onMeasure() did not set the"                           + " measured dimension by calling"                           + " setMeasuredDimension()");               }                  mPrivateFlags |= LAYOUT_REQUIRED;           }              mOldWidthMeasureSpec = widthMeasureSpec;           mOldHeightMeasureSpec = heightMeasureSpec;       }  

measure方法是final类型的,所以不能被继承,不能被复写。而measure方法里面调用了onMeasure方法,onMeasure方法可以被继承,可以被复写。下面是onMeasure源码:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/72df137146d57756eae6eff046afceac.html