Android View的绘制过程

直接了当的来说,Android系统中View的绘制需要经历三个主要过程: onMeasure()onLayout()onDraw()

onMeasure()过程负责确定View本身的所占空间和大小(长宽),onLayout()过程确定View在其父View中的具体位置并根据具体需求调整View的最终绘制大小,onDraw()则负责将View在Canvas中绘制出来。一般情况下,onMeasure()过程中确定的View的大小等同于onLayout()过程结束后View的大小。下面对于这三个过程进行一个详细的描述:

1.onMeasure()

任何一个View,在绘制自己之前都得明确一点,自己的长宽是多少。从源码中可以知道,View绘制的流程开始于ViewRoot的performTraversals()方法。在这个方法内部又会调用View的measure()方法,measure()方法接收两个int型参数widthMeasureSpec和heightMeasureSpec。我们来先来了解一下什么是MeasureSpec。

MeasureSpec
官方API文档中对它的解释是:
"A MeasureSpec encapsulates the layout requirements passed from parent to child. Each MeasureSpec represents a requirement for either the width or the height. A MeasureSpec is comprised of a size and a mode. There are three possible modes:
UNSPECIFIED
The parent has not imposed any constraint on the child. It can be whatever size it wants.
EXACTLY
The parent has determined an exact size for the child. The child is going to be given those bounds regardless of how big it wants to be.
AT_MOST
The child can be as large as it wants up to the specified size.
MeasureSpecs are implemented as ints to reduce object allocation. This class is provided to pack and unpack the <size, mode> tuple into the int."

一大堆的英文解释,简单看看就可以了。这么说吧,MeasureSpec就是View用来确定自己的大小的工具,任何一个View都需要通过父View传递给它的MeasureSpec中定义的specMode和specSize结合自身的定义文件(XML或代码中动态指定的长宽)来确定自己的大小。好的,弄清楚什么是MeasureSpec了我们现在回到measure()方法中去。

在上文中measure()方法中会调用到另一个方法onMeasure(),这个方法里才是Android系统中真正用来确定View的大小的地方。在onMeasure()中,系统通过调用setMeasuredDimension()来最终确定一个View的大小是多少。这就是一个View在Measure过程中所经历的步骤。当然,如果一个View是ViewGroup,它还需要根据上面的规则Measure每一个子View的大小。

2.onLayout()

Android的View是一个层叠的结构,我们通过复杂的计算确定了一个View的大小之后,接下来就要考虑的是该把这个View放在其父View什么位置。

ViewRoot的performTraversals()方法在完成View的Measure之后会进入到View的layout()方法中去。类似于View的Measure过程中,在这里View的layout()方法中会去调用onLayout()方法来做真正的布局过程。然而,当我们进入到onLayout()方法中去后会发现这是一个空的方法。Why?道理很简单,View的layout这件事情本身就是相对于父View来说的;对于父View(ViewGroup)来讲,每一种类型的布局如LinearLayout、RelativeLayout等的特性都不相同,因此这个onLayout()最合理的处理办法就是留给ViewGroup的子类自己去做实现。

由于系统自带的任意一种布局的onLayout()的过程都比较复杂,在这里限于篇幅就不做详细的分析。只有一点需要注意,Measure过程结束后我们拿到了View的大小信息,而在View的onLayout()方法里面系统默认的实现是将Measure后拿到的大小信息直接传递进来。实际上,我们完全可以在onLayout()方法中传入我们自定义的数字,这就是我之前提到过的View的onMeasure()结束后确定的大小一般情况下等于onLayout()结束后View的最终大小,但是这个结论不是永远都成立,就是因为我们可以自己去强制的改变其大小。在这里,相信我们也能解答很多人都会问的View的getMeasuredWidth()/getMeasuredHeight()和View的getWidth()/getHeight()的区别这个问题了。

3.onDraw()

Android系统要绘制一个View,我们先通过Measure过程确定View的大小,再通过Layout过程确定View的最终位置,最后我们就是要真正的把View会画出来。怎么画呢?Android给我提供了Canvas和Paint这一对好工具,我们简单的描述onDraw()这个过程:Canvas是个画布,Paint是支画笔,Android系统按照一定的规则使用Paint在Canvas按照View的规格把View给“画”出来,就是这么简单。

这个绘制过程,实际包含了以下几个步骤:

1).绘制View的背景(如果必要)
2).绘制View自身内容
3).绘制View的子视图
4).绘制Layer和fade edges
5).绘制ScrollBar

经过这几个步骤之后,Android系统就成功的将一个View绘制出来,变成了呈现在我们眼前的一个按钮、一个文本框或者一副图片等。

最后

通过以上几步简单的分析,相信大家对于View的绘制过程应该能有一定的理解了。对于源码的细节考究,就留给有心人自己去探索吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容