android--------自訂控制項 之 ViewGroup

來源:互聯網
上載者:User

標籤:--   col   參考資料   sdn   detail   技術分享   href   分享   out   

前面幾篇講了自訂控制項的群組控制項,地址:http://www.cnblogs.com/zhangqie/p/8985612.html

 

今天這篇博文主要來說說 自訂控制項的 ViewGroup。

 

什麼是ViewGroup?

ViewGroup是一種容器。它包含零個或以上的View及子View

 

ViewGroup有什麼作用?

ViewGroup內部可以用來存放多個View控制項,並且根據自身的測量模式,來測量View子控制項,並且決定View子控制項的位置。這在下面會逐步講解它是怎麼測量及決定子控制項大小和位置的。

 

自訂控制項

public class FlowLayoutb extends ViewGroup {    private int horizontolSpacing;    private int verticalSpacing;    public FlowLayoutb(Context context) {        super(context);        init(context);    }    public FlowLayoutb(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init(context);    }    private Line currentline;// 當前的行    private int useWidth = 0;// 當前行使用的寬度    private List<Line> mLines = new ArrayList<Line>();    private int width;    public FlowLayoutb(Context context, AttributeSet attrs) {        super(context, attrs);        init(context);    }    private void init(Context context) {        horizontolSpacing = Util.dip2px(13, context);        verticalSpacing = Util.dip2px(13, context);    }    // 測量 當前控制項Flowlayout    // 父類是有義務測量每個子View的    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        mLines.clear();        currentline = null;        useWidth = 0;        /**         * 獲得此ViewGroup上級容器為其推薦的寬和高,以及計算模式         */        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        // 計算出所有的childView的寬和高        measureChildren(widthMeasureSpec, heightMeasureSpec);        width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();        int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingBottom() - getPaddingTop(); // 擷取到寬和高        int childeWidthMode;        int childeHeightMode;        //  為了測量每個子View 需要指定每個子View測量規則        childeWidthMode = widthMode == MeasureSpec.EXACTLY ? MeasureSpec.AT_MOST : widthMode;        childeHeightMode = heightMode == MeasureSpec.EXACTLY ? MeasureSpec.AT_MOST : heightMode;        int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childeWidthMode, width);        int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childeHeightMode, height);        currentline = new Line();// 建立了第一行        for (int i = 0; i < getChildCount(); i++) {            View child = getChildAt(i);            // 測量每個子View            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);            int measuredWidth = child.getMeasuredWidth();            useWidth += measuredWidth;// 讓當前行加上使用的長度            if (useWidth <= width) {                currentline.addChild(child);//這時候證明當前的子View是可以放進當前的行裡,放進去                useWidth += horizontolSpacing;            } else {                //換行                newLine(child);            }        }        if (!mLines.contains(currentline)) {            mLines.add(currentline);// 添加最後一行        }        int totalheight = 0;        for (Line line : mLines) {            totalheight += line.getHeight();        }        totalheight += verticalSpacing * (mLines.size() - 1) + getPaddingTop() + getPaddingBottom();        System.out.println(totalheight);        setMeasuredDimension(width + getPaddingLeft() + getPaddingRight(), resolveSize(totalheight, heightMeasureSpec));    }    private void newLine(View child) {        mLines.add(currentline);// 記錄之前的行        currentline = new Line();// 建立新的一行        currentline.addChild(child);        useWidth = currentline.lineWidth;    }    private class Line {        int height = 0; //當前行的高度        int lineWidth = 0;        private List<View> children = new ArrayList<View>();        /**         * 添加一個子View         *         * @param child         */        public void addChild(View child) {            children.add(child);            if (child.getMeasuredHeight() > height) {                height = child.getMeasuredHeight();            }            lineWidth += child.getMeasuredWidth();        }        public int getHeight() {            return height;        }        /**         * 返回子View的數量         *         * @return         */        public int getChildCount() {            return children.size();        }        public void layout(int l, int t) {            lineWidth += horizontolSpacing * (children.size() - 1);            int surplusChild = 0;            int surplus = width - lineWidth;            if (surplus > 0 && children.size() > 0) {                surplusChild = surplus / children.size();            }            for (int i = 0; i < children.size(); i++) {                View child = children.get(i);                child.layout(l, t, l + child.getMeasuredWidth() + surplusChild, t + child.getMeasuredHeight());                l += child.getMeasuredWidth() + surplusChild;                l += horizontolSpacing;            }        }    }    // 分配每個子View的位置    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        l += getPaddingLeft();        t += getPaddingTop();        for (int i = 0; i < mLines.size(); i++) {            Line line = mLines.get(i);            line.layout(l, t);  //交給每一行去分配            t += line.getHeight() + verticalSpacing;        }    }}

 

 

自訂ViewGroup的步驟:

  1. 繼承ViewGroup,覆蓋構造方法
  2. 重寫onMeasure方法測量子控制項和自身寬高
  3. 實現onLayout方法擺放子控制項

 

 

 

 

 

 

源碼地址:https://github.com/DickyQie/android-custom-control

 

參考資料:

48055879

50533658

51089453

 

android--------自訂控制項 之 ViewGroup

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.