1. 程式人生 > >android 系統回撥onSizeChange, onMeasure, onLayout呼叫時機

android 系統回撥onSizeChange, onMeasure, onLayout呼叫時機

最新專案中常用到上面三個系統回撥,所以就在想,這三個用的時機到底是怎麼樣的?今天做了實驗:

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

<com.lotus.measure.ReSizeLayout xmlns:android="http://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,同級別的影響先決條件是,改變同級的大小或者位置,有時候沒有改變大小或者位置,也可能呼叫