普通View的measure流程

对于普通的view,其测量在ViewGroup中的measureChildWithMargins函数中调用child view的measure开始测量。

1:从measure函数开始

 1     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
 2         if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
 3                 widthMeasureSpec != mOldWidthMeasureSpec ||
 4                 heightMeasureSpec != mOldHeightMeasureSpec) {
 5
 6             // first clears the measured dimension flag
 7             mPrivateFlags &= ~MEASURED_DIMENSION_SET;
 8
 9             if (ViewDebug.TRACE_HIERARCHY) {
10                 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
11             }
12
13             // measure ourselves, this should set the measured dimension flag back
14             onMeasure(widthMeasureSpec, heightMeasureSpec);
15
16             // flag not set, setMeasuredDimension() was not invoked, we raise
17             // an exception to warn the developer
18             if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
19                 throw new IllegalStateException("onMeasure() did not set the"
20                         + " measured dimension by calling"
21                         + " setMeasuredDimension()");
22             }
23
24             mPrivateFlags |= LAYOUT_REQUIRED;
25         }
26
27         mOldWidthMeasureSpec = widthMeasureSpec;
28         mOldHeightMeasureSpec = heightMeasureSpec;
29     }

官方关于此函数的说明:measure函数用来计算一个view的尺寸,其传入的参数为parentView对此view的宽/高限制信息。实际的尺寸测量将会调用onMeasure来完成,因此,子类必须重写onMeasure函数。

通过measure函数的源码我们也可以知道:首先,它是final的,所以不可以重写;其次,它主要是对传入的parentView的宽高限制信息进行了是否与上一次的相同的判断,若是相同则不调用onMeasure重新测量;

2:measure ——> onMeasure函数

1     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
2         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
3                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
4     }

通过其代码,我们可以知道主要用了这三个函数,我们一一分析:

2.1:getSuggestedMinimumWidth函数:返回android:minWidth和背景宽度二者之间的最大值

 1 protected int getSuggestedMinimumWidth() {
 2     int suggestedMinWidth = mMinWidth; //mMinWidth对应android:minWidth属性所指定的值,如果它没有指定,那么默认为0
 3
 4     if (mBGDrawable != null) {   //如果设置了背景
 5         final int bgMinWidth = mBGDrawable.getMinimumWidth(); //背景的宽度,如果是ShapeDrawable那么为0,如果是BitmapDrawable则有原始宽高
 6         if (suggestedMinWidth < bgMinWidth) {  //如果设定的最小值小于背景图片宽度,那么设定最小值为背景图片宽度
 7             suggestedMinWidth = bgMinWidth;
 8         }
 9     }
10
11     return suggestedMinWidth;
12 }

2.2:getDefaultSize:如果measureSpec没有限定则返回size,否则返回measureSpec中的size

 1     public static int getDefaultSize(int size, int measureSpec) {
 2         int result = size;
 3         int specMode = MeasureSpec.getMode(measureSpec);
 4         int specSize =  MeasureSpec.getSize(measureSpec);
 5
 6         switch (specMode) {
 7         case MeasureSpec.UNSPECIFIED:
 8             result = size;
 9             break;
10         case MeasureSpec.AT_MOST:
11         case MeasureSpec.EXACTLY:
12             result = specSize;
13             break;
14         }
15         return result;
16     }

到此:我们可以总结getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec)的逻辑:如果parentView对尺寸没有限制(即parentView的模式为UNSPECIFIED),那么将返回view的suggested最小值,否则返回parentView指定的尺寸。getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)类似。

2.3 setMeasuredDimension:很简单,设置测量的宽高(注意不是view实际的宽高,实际的宽高要等layout完成之后才确定,虽然几乎全部就是measure后的宽高)

1     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
2         mMeasuredWidth = measuredWidth;
3         mMeasuredHeight = measuredHeight;
4
5         mPrivateFlags |= MEASURED_DIMENSION_SET;
6     }

至此,关于onMeasure函数分析结束。

时间: 2024-10-09 22:18:35

普通View的measure流程的相关文章

Android View体系(七)从源码解析View的measure流程

相关文章 Android View体系(一)视图坐标系 Android View体系(二)实现View滑动的六种方法 Android View体系(三)属性动画 Android View体系(四)从源码解析Scroller Android View体系(五)从源码解析View的事件分发机制 Android View体系(六)从源码解析Activity的构成 前言 在上一篇我们了解了Activity的构成后,开始了解一下View的工作流程,就是measure.layout和draw.measure

Android View measure流程详解

Android View measure流程详解 Android中View绘制的流程包括:measure(测量)->layout(布局)->draw(绘制). 因为Android中每个View都占据了一块矩形的空间,当我们要在屏幕上显示这个矩形的View的时候 首先我们需要知道这个矩形的大小(宽和高)这就对应了View的measure流程. 有了View的宽和高,我们还需要知道View左上角的起点在哪里,右下角的终点在哪里,这就对应了View的layout流程. 当矩形的区域在屏幕上确定之后,

Android View的绘制流程

View 绘制机制 1. View 树的绘图流程 当 Activity 接收到焦点的时候,它会被请求绘制布局,该请求由 Android framework 处理.绘制是从根节点开始,对布局树进行 measure 和 draw.整个 View 树的绘图流程在ViewRoot.java类的performTraversals()函数展开,该函数所做 的工作可简单概况为是否需要重新计算视图大小(measure).是否需要重新安置视图的位置(layout).以及是否需要重绘(draw),流程图如下: Vi

Android View的绘制流程三部曲 —— Measure

在刚开始学习Java的时候,我看的是Mars老师的视频.Mars老师说过的一句话让我印象很深刻:要有一颗面向对象的心. 如果我们用面向对象的思维方式来思考,就会觉的View的绘制机制是很合理,很科学的.我们要在一张纸上画一幅画,首先要测量一下这幅画有多大吧,然后确定在这张纸的哪个地方画会显得比较美观,最后才是用画笔工具将画绘制在纸上. 在Android中也是一样的.View的绘制流程主要是指measure,layout,draw这三步,即测量,布局,绘制.首先是要测量View的宽高,然后布局确定

View的measure机制

Android中View框架的工作机制中,主要有三个过程: 1.View树的测量(measure)Android View框架的measure机制     2.View树的布局(layout) Android View框架的layout机制     3.View树的绘制(draw)Android View框架的draw机制 View框架的工作流程为:测量每个View大小(measure)-->把每个View放置到相应的位置(layout)-->绘制每个View(draw). 1.系统为什么要有

深入理解 Android 之 View 的绘制流程

概述 本篇文章会从源码(基于Android 6.0)角度分析Android中View的绘制流程,侧重于对整体流程的分析,对一些难以理解的点加以重点阐述,目的是把View绘制的整个流程把握好,而对于特定实现细节则可以日后再对相应源码进行研读.在进行实际的分析之前,我们先来看下面这张图: 我们来对上图做出简单解释:DecorView是一个应用窗口的根容器,它本质上是一个FrameLayout.DecorView有唯一一个子View,它是一个垂直LinearLayout,包含两个子元素,一个是Titl

自定义控件知识储备-View的绘制流程

在自定义控件这个学习系列里,首先写篇文章记录一下View的绘制流程,压压惊:-P.也为以后的自定义控件实践打个基础.虽然讲解View工作流程的文章很多,其中不乏很多精品文章,不过自己能从中理清思路,以自己之言总结出来,也是十分必要的.好的,我要开始装-不,总结了. 1. 前言 当我们打开手机,开始看朋友圈,刷微博的时候,我们有考虑过在我们眼前的一个个View是如何从无到有的展示在我们眼前的么?有考虑过它们的感受么?(神经病才去考虑(ノ??)ノ彡┻━┻--). 当我们在一张纸上画画的时候,哪怕是简

从ViewRootImpl类分析View绘制的流程(一)

[出处:从ViewRootImpl类分析View绘制的流程 CSDN 废墟的树] 从上两篇博客 <从setContentView方法分析Android加载布局流程> 和 <从LayoutInflater分析XML布局解析成View的树形结构的过程> 中我们了解到Activity视图UI是怎么添加到Activity的根布局DecorView上面的. 我们知道Activity中的PhoneView对象帮我们创建了一个PhoneView内部类DecorView(父类为FrameLayou

自定义View的实现流程

1.继承View组件,比如,LabelView继承了View 2.重写两个构造方法,比如,对于自定义View LabelView LabelView(Context context),如果该自定义View是通过代码来实例化的,那么,就需要该构造方法: LabelView(Context context, AttributeSet attrs),通过布局文件XML来使用该自定义View,那么,就需要该构造方法. /** * Constructor.  This version is only ne