前言

  View的绘制过程分为 measure、layout、draw三个步骤,接下来对这三个步骤逐一进行研究。

measure方法的签名

public final void measure(int widthMeasureSpec, int heightMeasureSpec);

  measure方法用来测量View的尺寸。两个参数widthMeasureSpec/heightMeasureSpec声明了Parent View所能提供的宽/高。

  需要注意的是,widthMeasureSpec/heightMeasureSpec 这两个 int 型的参数是复合参数(compound parameters)。jvm中以32bit来存储int,最高两位表示“mode”,后面30位才是具体的数值。在View.java中有下面两个方法

        /**
* Extracts the mode from the supplied measure specification.
*
* @param measureSpec the measure specification to extract the mode from
* @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
* {@link android.view.View.MeasureSpec#AT_MOST} or
* {@link android.view.View.MeasureSpec#EXACTLY}
*/
public static int getMode(int measureSpec) {
return (measureSpec & MODE_MASK);
} /**
* Extracts the size from the supplied measure specification.
*
* @param measureSpec the measure specification to extract the size from
* @return the size in pixels defined in the supplied measure specification
*/
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}

  看到了吧,使用位操作&来获取最高两位的mode。2^2=4,这里只有用到了3种,它们分别的含义入下

  • UNSPECIFIED-ParentView对子View没有约束,后者可以是任意大小
  • AT_MOST-ParentView规定了尺寸上限,子View的大小不可以超过这个上限
  • EXACTLY-ParentView规定了子View的宽高,子View只能是这个宽高

  measure方法本身是声明为final的,CustomView必须实现自己的onMeasure方法,以便View.measure对此进行回调。在实现自己的CustomView.onMeasure之前,先来看看View中默认的onMeasure方法。

onMeasure

  在自定义View中,往往需要重写onMeasure方法,来设置View的measured width/height。要注意的一点是,计算完成后,必须调用setMeasuredDimension(int, int)来设置宽高,不然在上层measure方法会抛出IllegalStateException。自定View计算出的宽/高必须满足最小宽/高(通过getSuggestedMinimumWidth()、getSuggestedMinimumHeight()获取)。当然也可以在自定义View的onMeasure方法中直接调用View.onMeasure,如下

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

  然而,View默认的onMeasure实现逻辑非常简单,恐怕不能满足自定义View的需求。

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

  View.onMeasure简单粗暴地调用了setMeasuredDimension来设置measuredWidth/measuredHeight。其中使用的getDefaultSize(int, int)方法如下

    public static int getDefaultSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) {
case MeasureSpec.UNSPECIFIED:
result = size;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}

  逻辑很简单,一个switch/case语句,根据SpecMode来判断返回。若为UNSPECIFIED,则返回minimumWidth;若为AT_MOST/EXACTLY,返回SpecWidth。

  到此为止,View的measure过程已经完成了。对于ViewGroup,可以猜想,它的onMeasure方法,是把所有子View的onMeasure做一次相加。我们来看一下具体是不是这样做的。

ViewGroup.measure

  ViewGroup继承了View类,理所应当地,我们试图在ViewGroup中查找是否重写了onMeasure方法——未果。不过我们惊喜地发现了measureChildren这个方法——用来遍历所有children,对每一个child进行measure

    protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
final int size = mChildrenCount;
final View[] children = mChildren;
for (int i = 0; i < size; ++i) {
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) != GONE) {
measureChild(child, widthMeasureSpec, heightMeasureSpec);
}
}
}

  measureChild中,将ViewGroup的padding加入了计算,最后调用child.measure,这里不予深究,也不再贴出代码。

  ViewGroup.java本身并没有重写onMeasure方法,在它的具体实现中,onMeasure根据具体情况,将children的measured size进行求和处理,具体可以参阅FrameLayout/LiearLayout/RelativeLayout 的代码。

小结

  对于measure过程的分析就到这里,下一篇我们继续探讨onLayout过程。

Android UI 绘制过程浅析(二)onMeasure过程的更多相关文章

  1. Android UI 绘制过程浅析(五)自定义View

    前言 这已经是Android UI 绘制过程浅析系列文章的第五篇了,不出意外的话也是最后一篇.再次声明一下,这一系列文章,是我在拜读了csdn大牛郭霖的博客文章<带你一步步深入了解View> ...

  2. 传感器仿真平台——UI绘制模块(二)

    这一章讲的是UI绘制模块 该模块的作用是将实验对象绘制出来,它可能是目标.传感器等等,由于事先并不知道会有哪些物体,也无法事先定义好某个对象该怎么画,以我懒人的性格,得了,就抛给用的人吧~喝前摇一摇, ...

  3. Android UI 绘制过程浅析(四)draw过程

    前言 draw是绘制View三个步骤中的最后一步.同measure.layout一样,通常不对draw本身进行重写,draw内部会调用onDraw方法,子类View需要重写onDraw(Canvas) ...

  4. Android UI 绘制过程浅析(三)layout过程

    前言 上一篇blog中,了解到measure过程对View进行了测量,得到measuredWidth/measuredHeight.对于ViewGroup,则计算出全部children的宽高进行求和. ...

  5. Android UI 绘制过程浅析(一)LayoutInflater简介

    前言 这篇blog是我在阅读过csdn大牛郭霖的<带你一步步深入了解View>一系列文章后,亲身实践并做出的小结.作为有志向的前端开发工程师,怎么可以不搞懂View绘制的基本原理——简直就 ...

  6. Android UI绘制流程及原理

    一.绘制流程源码路径 1.Activity加载ViewRootImpl ActivityThread.handleResumeActivity() --> WindowManagerImpl.a ...

  7. 简单研究Android View绘制一 测量过程

    2015-07-27 16:52:58 一.如何通过继承ViewGroup来实现自定义View?首先得搞清楚Android时如何绘制View的,参考Android官方文档:How Android Dr ...

  8. Android UI开发第四十一篇——墨迹天气3.0引导界面及动画实现

    周末升级了墨迹天气,看着引导界面做的不错,模仿一下,可能与原作者的代码实现不一样,但是实现的效果还是差不多的.先分享一篇以前的文章,android动画的基础知识,<Android UI开发第十二 ...

  9. 简单研究Android View绘制三 布局过程

    2015-07-28 17:29:19 这一篇主要看看布局过程 一.布局过程肯定要不可避免的涉及到layout()和onLayout()方法,这两个方法都是定义在View.java中,源码如下: /* ...

随机推荐

  1. Java in a Nutshell学习笔记

    1, bytecode永远是大段 2,其它语言要在java里运行,要么实现类似于javac的编译器,把该语言解释成为class文件.要么,直接重新实现JVM,直接解释该语言3,Java和C++区别: ...

  2. redhat6.4安装storm集群-4节点

    0.搭建ftp服务器并建立yum源 1.在每个节点上安装java并设置环境变量 2.在三个节点上安装zookeeper 3.安装zeromq 过程中发现运行./configure时出现问题: conf ...

  3. 在 Vultr VPS 中 以 Debian 8 i386 (jessie) 为 操作系统 平台 手动 搭建 PPTP VPN 全过程

    更新服务器并安装 PPTP 服务  apt-get update apt-get upgrade apt-get install pptpd 编辑 /etc/pptpd.conf 找到 #locali ...

  4. 设计模式之二:MVC

    模型(Model) 视图(View) 控制器(Controller) (MVC) 是 Cocoa 中的一种行为模块,并且也是所有 Cocoa 设计模式中使用最多的.在程序中按照它们的角色来分类这些对象 ...

  5. java的eclipse操作和常用类Object的使用

    1.eclipse的快捷键: (1)alt + /   内容辅助. 如:main+alt + / 会出现完整的main方法. syso+alt+ / 会输出. 如编写某个方法时,只需写入方法名 + a ...

  6. android:LayoutInflater

    LayoutInflater:一般用于查找res/layout下的布局文件,findViewById()一般是用于查找布局下的各种控件 一般:我们使用LayoutInflater.from(conte ...

  7. [转]Centos 6.5 安装 Scrapy 0.22.2成功

    0. python -V               (此时显示为2.6.6) 1. yum -y update  2. yum groupinstall -y development  3. yum ...

  8. MVC 3.0 Tree

    页面分左右两部分,左边是一个导航树,右边是局部页,点击树节点,异步刷新右边的内容.加颜色部分是知识点. @using VideoWeb.Models@model VideoWeb.Models.Cat ...

  9. C++ Primer : 第十三章 : 拷贝控制之拷贝控制和资源管理

    定义行为像值的类 行为像值的类,例如标准库容器和std::string这样的类一样,类似这样的类我们可以简单的实现一个这样的类HasPtr. 在实现之前,我们需要: 定义一个拷贝构造函数,完成stri ...

  10. c++构造函数的作用---13

    原创博客:转载请标明出处:http://www.cnblogs.com/zxouxuewei/ http://blog.csdn.net/tidyjiang/article/details/52073 ...