讓自定義ViewGroup支持Padding

自定義控件系列:
秒懂OnMeasure
秒懂OnLayout
讓自定義ViewGroup裏的子控件支持Margin
讓自定義ViewGroup支持Padding
自定義ViewGroup的一個綜合實踐 FlowLayout

知識點:

  1. 讓自定義ViewGroup支持Padding,需要自定義ViewGroup在自身的onMeasure和onLayout裏去處理Padding即可

因爲padding很容易獲得,不像是Margin那麼麻煩,
另外與margin不同的是,padding是自定義ViewGroup的padding,只有四個padding,而margin是子控件的margin,每個子控件都會有四個margin,所有在處理上注意一下

應用

1. 支持padding

第一步:onMeasure裏處理Padding

其實就是在AT_MOST模式下,讓ViewGroup自身的寬高加上padding,變大一點
EXACTLY模式是不用處理的,因爲他已經指定了寬高,按照他指定的來就行了

在這裏插入圖片描述

  /**
     * 計算本View在AtMost模式下的寬高
     * 其他代碼都是不用動的,在這裏寫下你特有的邏輯就可以
     *
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     * @return
     */
    private Point caculateAtMostSize(int widthMeasureSpec, int heightMeasureSpec) {

        int width = 0;
        int height = 0;

        int count = getChildCount();
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            // 測量一下子控件的寬高
            measureChild(child, widthMeasureSpec, heightMeasureSpec);

            // 得到MarginLayoutParams,margin就在這裏保存着
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            // 獲得子控件的寬高(需要加上對應的margin,讓控件的寬高包含margin,
            // 這樣才能讓自定義的viewgroup在計算自身在AtMost模式的尺寸時候考慮到這些margin)
            int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;

            // 因爲我們的自定義View模擬的是豎向的LinearLayout,所以:
            // 控件的寬度爲所有子控件裏,寬度最大的那個view的寬度,
            // 控件高度是所有子空間的高度之和
            width = Math.max(childWidth, width);
            height += childHeight;
        }

        width += (getPaddingLeft() + getPaddingRight());
        height += (getPaddingTop() + getPaddingBottom());
        return new Point(width, height);
    }
第二步:onLayout裏處理Padding

在這裏插入圖片描述

  @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int top = getPaddingTop();
        int count = getChildCount();
        for (int i = 0; i < count; i++) {

            View child = getChildAt(i);

            // 得到MarginLayoutParams,margin就在這裏保存着
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();


            // 獲得子控件的寬高(需要加上對應的margin,讓控件的寬高包含margin)
            int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;

            // 佈局,就是設置好這個子控件的左上右下
            // 在佈局的時候,考慮控件的margin,把子view擺放好
            // (這是一個豎向的LinearLayout,想想如何佈置子控件)
            child.layout(lp.leftMargin+getPaddingLeft(),
                    top + lp.topMargin,
                    childWidth - lp.rightMargin+getPaddingLeft(),
                    top + childHeight - lp.bottomMargin);
            top += childHeight;

        }

    }

github源碼之MyLinearLayoutWithMarginAndPadding

至此

  1. 自定義View(含Viewgroup)onMeasure裏支持AT_MOST的模板代碼
  2. 自定義Viewgroup的onLayout裏支持Margin的模板代碼
    都有了,真的是一樣的套路,照抄即可
  3. 另外處理Margin和Padding的一些小邏輯,仔細想想也很容易寫出來,大思路有了,小邏輯調試一下就出來了

參考:
《Android自定義開發入門與實踐》感謝大神的著作

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章