自定義ViewGroup,你真正懂了嗎?

LoreneXJE 8年前發布 | 23K 次閱讀 安卓開發 Android開發 移動開發

背景

自定義View簡單,因為它只需管好自己即可,而自定義ViewGroup不僅僅要管好自己,還要管好子View。接觸過ViewGroup的童鞋應該都清楚,ViewGroup是作為一個View的容器,它裝著子View并將子View放到指定位置上去。

目的

讓大家舉一反三地去自定義定制化的GroupView

思路

自定義GroupView思路

  • 首先需要知道子View大小,然后才能確定自定義的GroupView如何設置才能容納它們。

  • 根據子View的大小和ViewGroup需要實現的效果,確定最終ViewGroup的大小。

  • ViewGroup和子View的大小確定后,接著就是如何去擺放子View,你可以按照自己特定的規則去擺放。

  • 然后將子View對號入座放入已知的分割單元。

實踐

接下來我做一個示例將子View按從左到右順序一個挨著一個擺放,即模仿實現LinearLayout的橫向布局。

首先重寫onMeasure,測量子View大小以及設定ViewGroup最終大小,代碼如下:

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // 對所有子view進行測量,觸發所有子view的onMeasure函數
        measureChildren(widthMeasureSpec, heightMeasureSpec);

    // 寬度模式
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    // 測量寬度
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    // 高度模式
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    // 測量高度
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    // 子view數目
    int childCount = getChildCount();
    if (childCount == 0){
        // 如果當前ViewGroup沒有子View,就沒有存在的意義,無需占空間
        setMeasuredDimension(0, 0);
    }else {
        // 如果寬高都是包裹內容
        if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST){
            // 寬度為所有子view寬度相加,高度取子view最大高度
            int width = getTotalWidth();
            int height = getMaxHeight();
            setMeasuredDimension(width, height);
        }else if (widthMode == MeasureSpec.AT_MOST){
            // 寬度為所有子View寬度相加,高度為測量高度
            setMeasuredDimension(getTotalWidth(), heightSize);
        }else if (heightMode == MeasureSpec.AT_MOST){
            // 寬度為測量寬度,高度為子view最大高度
            setMeasuredDimension(widthSize, getMaxHeight());
        }
    }
}

  /**
 * 獲取子view最大高度
 * @author leibing
 * @createTime 2016/09/19
 * @lastModify 2016/09/19
 * @param
 * @return
 */
private int getMaxHeight() {
    // 最大高度
    int maxHeight = 0;
    // 子view數目
    int childCount = getChildCount();
    // 遍歷子view拿取最大高度
    for (int i=0;i<childCount;i++){
        View childView = getChildAt(i);
        if (childView.getMeasuredHeight() > maxHeight)
            maxHeight = childView.getMeasuredHeight();
    }

    return maxHeight;
}

/**
 * 所有子view寬度相加
 * @author leibing
 * @createTime 2016/09/19
 * @lastModify 2016/09/19
 * @param
 * @return
 */
private int getTotalWidth() {
    // 所有子view寬度之和
    int totalWidth = 0;
    // 子View數目
    int childCount  = getChildCount();
    // 遍歷所有子view拿取所有子view寬度之和
    for (int i=0;i<childCount;i++){
        View childView = getChildAt(i);
        totalWidth += childView.getMeasuredWidth();
    }
    return totalWidth;
}</code></pre> 

接下來將子View擺放到合適的位置上去,代碼如下:

@Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // 子view數目
        int childCount = getChildCount();
        // 記錄當前寬度位置
        int currentWidth = l;
        // 逐個擺放子view
        for (int i = 0;i<childCount;i++){
            View childView = getChildAt(i);
            int height = childView.getMeasuredHeight();
            int width = childView.getMeasuredWidth();
            // 擺放子view,參數分別是子view矩形區域的左、上,右,下。
            childView.layout(currentWidth, t, currentWidth + width, t + height);
            currentWidth += width;
        }
    }

運行效果圖如下所示:

CustomViewGroup.gif

童鞋們,看完后,自定義ViewGroup是不是很簡單了?

 

來自:http://www.jianshu.com/p/07ac5921fed8

 

 本文由用戶 LoreneXJE 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!