Android流式布局實現,android流布局

來源:互聯網
上載者:User

Android流式布局實現,android流布局

查看我的全部開源項目【開源實驗室】
歡迎加入我的QQ群:【201055521】,本部落格用戶端下載【請點擊】

摘要

新項目用到了一種全新布局————Android標籤流式布局的功能,正好一直說給大家講自訂控制項的實現,今天就為大家講一種android流式布局的實現。
本文原創,轉載請註明地址:http://blog.kymjs.com/

本文

在日常的app使用中,我們會在android 的app中看見熱門標籤等自動換行的流式布局,今天,我們就來看看如何自訂一個類似熱門標籤那樣的流式布局吧(源碼下載在下面最後給出)

這個控制項並不是我實現的,代碼是從網上搜流式布局找到的。我只是為大家講解一下實現過程以及原理。

先看代碼
public class FlowLayout extends ViewGroup {    private float mVerticalSpacing; //每個item縱向間距    private float mHorizontalSpacing; //每個item橫向間距    public FlowLayout(Context context) {        super(context);    }    public FlowLayout(Context context, AttributeSet attrs) {        super(context, attrs);    }    public void setHorizontalSpacing(float pixelSize) {        mHorizontalSpacing = pixelSize;    }    public void setVerticalSpacing(float pixelSize) {        mVerticalSpacing = pixelSize;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int selfWidth = resolveSize(0, widthMeasureSpec);        int paddingLeft = getPaddingLeft();        int paddingTop = getPaddingTop();        int paddingRight = getPaddingRight();        int paddingBottom = getPaddingBottom();        int childLeft = paddingLeft;        int childTop = paddingTop;        int lineHeight = 0;        //通過計算每一個子控制項的高度,得到自己的高度        for (int i = 0, childCount = getChildCount(); i < childCount; ++i) {            View childView = getChildAt(i);            LayoutParams childLayoutParams = childView.getLayoutParams();            childView.measure(                    getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight,                            childLayoutParams.width),                    getChildMeasureSpec(heightMeasureSpec, paddingTop + paddingBottom,                            childLayoutParams.height));            int childWidth = childView.getMeasuredWidth();            int childHeight = childView.getMeasuredHeight();            lineHeight = Math.max(childHeight, lineHeight);            if (childLeft + childWidth + paddingRight > selfWidth) {                childLeft = paddingLeft;                childTop += mVerticalSpacing + lineHeight;                lineHeight = childHeight;            } else {                childLeft += childWidth + mHorizontalSpacing;            }        }        int wantedHeight = childTop + lineHeight + paddingBottom;        setMeasuredDimension(selfWidth, resolveSize(wantedHeight, heightMeasureSpec));    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        int myWidth = r - l;        int paddingLeft = getPaddingLeft();        int paddingTop = getPaddingTop();        int paddingRight = getPaddingRight();        int childLeft = paddingLeft;        int childTop = paddingTop;        int lineHeight = 0;        //根據子控制項的寬高,計運算元控制項應該出現的位置。        for (int i = 0, childCount = getChildCount(); i < childCount; ++i) {            View childView = getChildAt(i);            if (childView.getVisibility() == View.GONE) {                continue;            }            int childWidth = childView.getMeasuredWidth();            int childHeight = childView.getMeasuredHeight();            lineHeight = Math.max(childHeight, lineHeight);            if (childLeft + childWidth + paddingRight > myWidth) {                childLeft = paddingLeft;                childTop += mVerticalSpacing + lineHeight;                lineHeight = childHeight;            }            childView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);            childLeft += childWidth + mHorizontalSpacing;        }    }}
從控制項建立過程說起流布局的實現

看到onMeasure()方法中的這段:

//通過計算每一個子控制項的高度,得到自己的高度for (int i = 0, childCount = getChildCount(); i < childCount; ++i) {        View childView = getChildAt(i);        LayoutParams childLayoutParams = childView.getLayoutParams();        childView.measure(                getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight,                        childLayoutParams.width),                getChildMeasureSpec(heightMeasureSpec, paddingTop + paddingBottom,                        childLayoutParams.height));        int childWidth = childView.getMeasuredWidth();        int childHeight = childView.getMeasuredHeight();        lineHeight = Math.max(childHeight, lineHeight);        if (childLeft + childWidth + paddingRight > selfWidth) {            childLeft = paddingLeft;            childTop += mVerticalSpacing + lineHeight;            lineHeight = childHeight;        } else {            childLeft += childWidth + mHorizontalSpacing;        }    }

首先通過迴圈,遍曆這個控制項的所有子控制項,同時調用子控制項的measure()方法,這時measure方法的兩個參數是控制項能給這個子控制項的最大寬高(我們都知道的,子控制項再大,顯示的大小也不能比父控制項還大)。這裡getChildMeasureSpec()方法的作用是用來計算一個合適子視圖的尺寸大小(寬度或者高度),結合我們從子視圖的LayoutParams所給出的MeasureSpec資訊來擷取最合適的結果。比如,如果這個View知道自己的大小尺寸(因為它本身的MeasureSpec的model為Exactly,)並且子視圖的大小恰好跟父視窗一樣大,父視窗必須用給定的大小去layout子視圖
參數含義:spec 父視窗傳遞給子視圖的大小和模式
padding 父視窗的邊距,也就是xml中的android:padding
childDimension 子視圖想要繪製的準確大小,但最終不一定繪製此值

當得到了每一個子控制項的大小以後,再要計算自己的寬高就簡單了。
int wantedHeight = childTop + lineHeight + paddingBottom;

同理,在onLayout中的這一句

for (int i = 0, childCount = getChildCount(); i < childCount; ++i) {        View childView = getChildAt(i);        if (childView.getVisibility() == View.GONE) {            continue;        }        int childWidth = childView.getMeasuredWidth();        int childHeight = childView.getMeasuredHeight();        lineHeight = Math.max(childHeight, lineHeight);        if (childLeft + childWidth + paddingRight > myWidth) {            childLeft = paddingLeft;            childTop += mVerticalSpacing + lineHeight;            lineHeight = childHeight;        }        childView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);        childLeft += childWidth + mHorizontalSpacing;    } 

首先通過迴圈遍曆,控制每個item子控制項的顯示位置,如果當前行還能放得下一個item,就放到當前行,如果放不下就放到下一行的最左邊。
最終,遍曆完成,也就相當於把自己的位置顯示完成了。

效果

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.