LotusLoveNature

日常工作,生活小记

android 系统回调onSizeChange, onMeasure, onLayout调用时机

最新项目中常用到上面三个系统回调,所以就在想,这三个用的时机到底是怎么样的?今天做了实验:

<?xml version="1.0" encoding="utf-8"?>

<com.lotus.measure.ReSizeLayout xmlns:android="https://schemas.android.com/apk/res/android"

    android:id="@+id/root_layout"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical" >


    <com.lotus.measure.MyEditText

        android:layout_width="fill_parent"

        android:layout_height="wrap_content" />


    <com.lotus.measure.MyLinearLayout

        android:id="@+id/bottom_layout"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"

        android:gravity="bottom"

        android:orientation="vertical" >


        <Button

            android:id="@+id/button"

            android:layout_width="fill_parent"

            android:layout_height="100dp"

            android:text="haha" >

        </Button>


        <com.lotus.measure.MyTextView

            android:id="@+id/textview"

            android:layout_width="fill_parent"

            android:layout_height="wrap_content"

            android:background="#77777777"

            android:text="hello" />

    </com.lotus.measure.MyLinearLayout>

</com.lotus.measure.ReSizeLayout>

按照上面的层次关系,每个view自定义一下,就是为了将三个方法打印出来,打印结果:

01-19 17:17:44.985: I/cdd(15351): ReSizeLayout--------onSizeChanged--480,741,0,0

01-19 17:17:44.985: I/cdd(15351): MyEditText--------onSizeChanged--480,65,0,0

01-19 17:17:44.985: I/cdd(15351): MyEditText--------onLayout--0,0,480,65

01-19 17:17:44.985: I/cdd(15351): MyLinearLayout--------onSizeChanged--480,676,0,0

01-19 17:17:44.985: I/cdd(15351): MyTextView--------onSizeChanged--480,25,0,0

01-19 17:17:44.985: I/cdd(15351): MyTextView--------onLayout--0,651,480,676

01-19 17:17:44.985: I/cdd(15351): MyLinearLayout--------onLayout--0,65,480,741

01-19 17:17:44.985: I/cdd(15351): ReSizeLayout--------onLayout--0,0,480,741

01-19 17:17:44.985: I/cdd(15351): MyEditText--------onMeasure--480,741

01-19 17:17:44.985: I/cdd(15351): MyTextView--------onMeasure--480,526

01-19 17:17:44.985: I/cdd(15351): MyLinearLayout--------onMeasure--480,676

01-19 17:17:44.985: I/cdd(15351): ReSizeLayout--------onMeasure--480,741

01-19 17:17:44.985: I/cdd(15351): MyEditText--------onLayout--0,0,480,65

01-19 17:17:44.985: I/cdd(15351): MyTextView--------onLayout--0,651,480,676

01-19 17:17:44.985: I/cdd(15351): MyLinearLayout--------onLayout--0,65,480,741

01-19 17:17:44.995: I/cdd(15351): ReSizeLayout--------onLayout--0,0,480,741

感觉执行顺序是这样的:

1. 首先是执行叶子child的onMeasure方法,逐层向上调用,最后调用到root的onMeasure,onMeasure本身的作用就是告诉父亲自己占用多大的位置,根据递归原理,onMeasure的确应该从下往上层调用

2. 调用到root的onMeasure后,其实这个统计大小的工作肯定是比root还高级别的View触发,也许就是DecorView,统计完大小后,开始调用onSizeChange,我想这里调用onSizeChange是因为首次显示的原因,调用onSizeChange是从root开始的,然后逐级调用到child,调用每个child的onSizeChange完毕后,每个child执行layout动作

3. 从顺序来看,layout动作和onMeasure一样,都是从小往上层调用。从叶子child的onlayout调用开始,最后调用到root的onlayout方法。因为只有大小发生了变化才会执行onSizeChange,所以没有onSizeChange的时候,就是从尾到头执行完onmeasure,再开始从尾到头执行完onlayout

4. 由此看来,onSizeChange并不一定会调用,只有View的大小发生变化才会调用,而且也不一定一定从root开始调用。onMeasure在整个界面上需要放置一样东西或拿掉一样东西时会调用。比如addView就是放置,removeview就是拿掉,另外比较特殊的是,child设置为gone会触发onMeasure,但是invisible不会触发onMeasure。一旦执行过onMeasure,往往就会执行onLayout来重新布局

5. 分支影响整个分支直到root,比如上面的root有两个孩子,这两个孩子是不同的分支,这两个孩子是同级别,如果又孩子在点击button的时候让textview消失掉

01-19 17:40:56.185: I/cdd(15481): MyLinearLayout--------onMeasure--480,676

01-19 17:40:56.185: I/cdd(15481): ReSizeLayout--------onMeasure--480,741

01-19 17:40:56.185: I/cdd(15481): MyLinearLayout--------onLayout--0,65,480,741

01-19 17:40:56.185: I/cdd(15481): ReSizeLayout--------onLayout--0,0,480,741

它会影响右分支所有直到root,所以同一分支比较容易影响。但是我们看到没有影响到左孩子

为什么没有影响到做孩子呢,是因为没有影响到他的大小或者位置。

比如,在root下面加入一个孩子,如果孩子是加在前面两个孩子后面,那么对前面两个孩子都没有影响。但是如果加在两个孩子中间,那么对第二个孩子影响,影响的话就会执行onmeasure和onlayout

a.加在两个孩子后面

01-19 17:53:53.235: I/cdd(15939): ReSizeLayout--------onMeasure--480,741

01-19 17:53:53.235: I/cdd(15939): ReSizeLayout--------onLayout--0,0,480,741

b.加在两个孩子中间

01-19 17:45:55.345: I/cdd(15846): MyTextView--------onMeasure--480,454

01-19 17:45:55.345: I/cdd(15846): MyLinearLayout--------onMeasure--480,604

01-19 17:45:55.345: I/cdd(15846): ReSizeLayout--------onMeasure--480,741

01-19 17:45:55.345: I/cdd(15846): MyLinearLayout--------onSizeChanged--480,604,480,676

01-19 17:45:55.345: I/cdd(15846): MyTextView--------onLayout--0,579,480,604

01-19 17:45:55.345: I/cdd(15846): MyLinearLayout--------onLayout--0,137,480,741

01-19 17:45:55.345: I/cdd(15846): ReSizeLayout--------onLayout--0,0,480,741

6. 一个分支下的影响很可能就是一条线到root,同级别的影响先决条件是,改变同级的大小或者位置,有时候没有改变大小或者位置,也可能调用



评论
©LotusLoveNature | Powered by LOFTER