最簡單的自定義ViewGroup

FlowLayout

子View們的寬度加起來超過一行,會自動換行顯示。java

flowlayout.png

核心就兩步:git

  • 在Layout中的onMeasure方法中調用子View的measure(),這兒雖然用的是measureChild方法,但最終仍是去調用子View的measure()
  • 在Layout中的onLayout方法中調用子View的layout()

再複雜的自定義View都是這樣從最簡單的形式,不斷增長代碼,迭代出來的 github

最簡單的自定義ViewGroup:app

public class FlowLayout extends ViewGroup {

    public FlowLayout(Context context) {
        this(context, null);
    }

    public FlowLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        int layoutWidth = r-l;
        int left = 0;
        int right = 0;
        int top = 0;
        for (int i = 0; i < childCount; i++) {
            View view = getChildAt(i);
            // 換行:比較right,right若是大於Layout寬度,那麼要換行
            right = left + view.getMeasuredWidth();
            if (right > layoutWidth) {
                left = 0;
                right = left + view.getMeasuredWidth();
                top += view.getMeasuredHeight();
            }
            getChildAt(i).layout(left, top, right, top + view.getMeasuredHeight());
            left += view.getWidth();
        }
    }

}

在最簡單的實現下,咱們能夠考慮更多,固然代碼也就更多,如:

  • 處理子View不可見的狀況
  • 添加對MeasureSpec.AT_MOST的支持
  • 添加對layout_margin的支持

上述這些我也都實現了,但還有一個我沒有去弄,對gravity的支持(由於其非必需就暫時不加,我現有其它事),若是你有興趣完成它,能夠fork,弄好了pull request。ide

完整代碼查看this

相關文章
相關標籤/搜索