Android View 框架(3)-- layout

本篇你將了解到:

  1. layout 方法的作用
  2. onLayout 方法是如何布局子 View 的
  3. 實戰(zhàn),如何快樂的自定義 View

在經(jīng)過第一步的測量后,成功計算了每一個 View 的尺寸。但是要成功的把 View 繪制到屏幕上,只有 View 的尺寸還不行,還需要準(zhǔn)確的知道該 View 應(yīng)該被繪制到什么位置。

layout 方法

每一個 parent 會調(diào)用 children 的 layout 方法,來設(shè)置 children view 的位置。我們簡要的給出 layout 的偽代碼,去看看里面具體做了什么工作。

public void layout(int l, int t, int r, int b) {
    if (根據(jù)一些flag,發(fā)現(xiàn)需要進一步measure) {
        onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
    }
    // 暫存舊的位置信息
    int oldL = mLeft;
    int oldT = mTop;
    int oldB = mBottom;
    int oldR = mRight;
    // 設(shè)置新的位置信息
    mLeft = l;
    mTop = t;
    mBottom = b;
    mRight = r;
 
    if (layout改變了 || 需要layout) {
        onLayout(changed, l, t, r, b);
          
  // 回調(diào) layoutChange 事件
        for (遍歷監(jiān)聽對象) {
            listener.onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
        }
    }
    // 標(biāo)記為已經(jīng)執(zhí)行過layout
}

根據(jù)以上偽代碼可得知,layout 方法的工作主要為以下三點:

  1. 修改當(dāng)前 view 的位置;
  2. 如果位置變化了的話,執(zhí)行 onLayout 方法;
  3. 調(diào)用所有監(jiān)聽器的 onLayoutChange 事件;

1,3 兩點是很好理解的,那 2 中,onLayout 方法是用來做什么的呢?

onLayout 方法

每一個 ViewGroup 的子類,都需要求重寫 onLayout 這個抽象方法,來確定子 View 在 ViewGroup 中的是如何布局的。
所以在上方 layout 方法中,代表著如果當(dāng)前 View 的布局發(fā)生變化后,需要取重新布局一下所有的子 View。

我們根據(jù)幾種熟悉的布局,如 LinearLayoutRelativeLayoutonLayout 方法的源碼,可以得出以下規(guī)律。

protected void onLayout(boolean changed, int l, int t, int r, int b) {
    for (遍歷子View) {
        /**
        根據(jù)如下數(shù)據(jù)計算。
            1、自己當(dāng)前布局規(guī)則。比如垂直排放或者水平排放。
            2、子View的測量尺寸。
            3、子View在所有子View中的位置。比如位置索引,第一個或者第二個等。
        */
        child.layout(上面計算出來的位置信息);
    }        
}     

實戰(zhàn):自定義View

我們需要達(dá)到以下效果:

  1. 每一個子 View 在豎直方向上線性分布;
  2. 每一個子 View 在水平方向,逐個向右偏移量增加 30dp;
  3. 使用 wrap_content 時,能達(dá)到剛剛好包裹住子 View;
  4. 使用 match_parent 時,充滿父 View;
效果圖

xml 文件格式

<com.lijing.dev.todo.view.AViewGroup
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <com.lijing.dev.todo.view.BView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/res_yellow" />

    <com.lijing.dev.todo.view.BView
        android:layout_width="80dp"
        android:layout_height="60dp"
        android:background="#8BC34A" />


    <com.lijing.dev.todo.view.BView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#E91E63" />

</com.lijing.dev.todo.view.AViewGroup>

代碼就不貼了,沒有任何意義,想看的去我練舞房Github看:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容