简略理解Android View中的onMeasure和onLayout方法

本文仅简略地解释了onMeasure和onLayout的调用流程,不涉及调用过程中的参数意义的解释

+---------------------------+                                
|        LinearLayout       |                                
|                           |                                
| +-----------------------+ |                                
| |       TextView        | |                                
| |                       | |                                
| +-----------------------+ |                                
| +-----------------------+ |                                
| |       TextView        | |                                
| |                       | |                                
| +-----------------------+ |                                
+---------------------------+                                
             [1]                                             

假设当前Activity的页面层次架构如图[1]所示。一个LinearLayout中有两个TextView。

概述

总过程分两步:onMeasure过程和onLayout过程。onMeasure过程决定各个view的大小,onLayout过程决定view的位置。每个过程都从上往下地递归调用。

onMeasure过程

         +--------------+        +--------------+    +--------------+      
         | LinearLayout |        |   TextView   |    |   TextView   |      
         +-------+------+        +-------+------+    +-------+------+      
                 |                       |                   |             
  child.measure  |                       |                   |             
+--------------> |                       |                   |             
     [1]         |                       |                   |             
            onMeasure                    |                   |             
                 |      child.measure    |                   |             
                 |   +--------------->   |                   |             
                 |          [2]      onMeasure               |             
                 |                       |                   |             
                 |                       |    child.measure  |             
                 |   +-------------------------------------->+             
                 |                       |         [3]       |             
                 |                       |               onMeasure         
                 |                       |              setMeasureDimension
                 |                       |                   |    [4]      
                 |   <---------+-----------------------------+             
                 |             |         |                   |             
                 |             |         |                   |             
                 |             |   setMeasureDimension       |             
                 |             |         |                   |             
         setMeasureDimension   +---------+                   |             
                 | [5]                   |                   |             
                 |                       |                   |             
 <---------------+                       |                   |             
                 +                       +                   + 
  • LinearLayout的父view/layout调用LinearLayout的measure方法,measure方法调用onMeasure方法。

  • onMeasure方法的目的是让layout(这里是LinearLayout)根据传入的两个MeasureSpec参数(代表父view当前分配给子view的Dimension),设置好自己‘想要’的Dimension大小

  • Linearlayout怎么知道自己“想要”多大呢?必须要先知道自己的子view的“想要”大小。于是它会调用各个子view的measure方法。当子View分配好自己的大小后,便开始计算自己的大小,最后调用setMeasuredDimension方法保存“想要”的Dimension。计算完毕后直接返回父View。

  • 值得注意的是,该过程(1-5)可能会调用多遍,来确认子view的大小(什么时候需要再次调用measure有待研究…)。

如图所示,LinearLayout首先要知道两个TextView的大小,然后根据结果调整自己的高度/宽度。

onLayout过程

         +--------------+        +--------------+    +--------------+      
         | LinearLayout |        |   TextView   |    |   TextView   |      
         +-------+------+        +-------+------+    +-------+------+      
                 |                       |                   |             
                 |                       |                   |             
                 |                       |                   |             
  child.layout   |                       |                   |             
+--------------> |                       |                   |             
      [1]        |                       |                   |             
                 |                       |                   |             
                 |                       |                   |             
              onLayout                   |                   |             
                 | [2]                   |                   |             
                 |                       |                   |             
                 |                       |                   |             
                 |      child.layout     |                   |             
                 |   +--------------->   |                   |             
                 |          [3]          |                   |             
                 |                       |                   |             
                 |                    onLayout               |             
                 |                       | [4]               |             
                 |                       |                   |             
                 |                       |    child.layout   |             
                 |   +-------------------------------------> |             
                 |                       |                   |             
                 |                       |               onLayout          
                 |                       |                   | [5]         
                 |                       |                   |             
                 +                       +                   + 
  • LinearLayout的父view/layout调用LinearLayout的layout方法,layout方法调用onlayout方法。

  • 对于ViewGroup来说,onLayout方法的意义是“决定子view的具体位置”,即ViewGroup通过调用子view的layout方法,传入4个参数(top,left,right,bottom),子view应该按照这四个参数渲染自己(draw)。

如图所示,LinearLayout告诉第一个TextView它所在的位置。第二个TextView的位置应该是原位置加上第一个TextView的高度(还有一些边距等)。

最后

  • onMeasure和onLayout过程结束后,便开始递归调用onDraw方法渲染整个层次结构。
  • AbsoluteLayout的源码十分简单,可以参考它来学习上述两个方法。

发表评论

您的电子邮箱地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据