流式布局FlowLayout


public class FlowLayout extends ViewGroup {
    private int mHorizonalSpace=8;
    private int mVerticalSpace=8;
    /** 当前的流式布局不确定有几行,可能有多行也可能没有行.**/
    private List mLines=new ArrayList();
    private int mContainerWidth;
    private int mContainerHeight;
    /***
    行对象
    */
    private class Line
    {
        private int lineWidth=0;
        private int lineHeight=0;
        /**存放行的元素 **/
        private List views=new ArrayList();
        public int getLineWidth() {
            return lineWidth;
        }
        public int getLineHeight() {
            return lineHeight;
        }
        public List getViews() {
            return views;
        }
        
        // 还需要支持往行里面添加元素
        public void addChild(View view) {
            // 如果当前行不存在这个元素的话就把元素添加进来
            if (!views.contains(view)) {
                
                // 测量
                view.measure(0, 0);
                if (views.size() ==0) {
                    // 当前只有一个元素的,宽与高就由它决定
                    lineWidth += view.getMeasuredWidth() + mHorizonalSpace;
                    lineHeight = view.getHeight();
                } else {
                    // 有不同高度的元素
                    lineWidth += view.getMeasuredWidth() + mHorizonalSpace;
                    lineHeight = Math.max(lineHeight, view.getMeasuredHeight());
                }
                views.add(view);
            }
        }
    }
    public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }
    /**.xml  画页面, 所见即所得 */
    public FlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
    /**.java  new FlowLayout(context)  动态输出*/
    public FlowLayout(Context context) {
        super(context);
        init(context);
    }

    /*** 方法
    @param context
    */
    private void init(Context context) {
        //setBackgroundColor(Color.BLUE);
    
    }
    /*** 方法  一。测量
    @param widthMeasureSpec
    @param heightMeasureSpec
    */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mLines.clear();
        // 一。容器它是占满屏幕
        
        mContainerWidth = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
        
        // 二。高度是由行数决定, 所以针对所有控件进行测量宽高,分行就可以算出行数了.
        int childCount = getChildCount();
        Line currLine = null;
        for (int i = 0; i < childCount; i++) {
            // 获取每个元素
            View child = getChildAt(i);
            // 测宽高
            child.measure(0, 0);
            int cHeight = child.getMeasuredHeight();
            int cWidth = child.getMeasuredWidth();
            //为第一个元素创建行
            if (mLines.size() == 0) {
                // 新建一行
                currLine = new Line();
                mLines.add(currLine);
            }
            //如果未满一行往里添加
            int remainWidth = mContainerWidth - currLine.getLineWidth();
            if (remainWidth >=cWidth) {
                currLine.addChild(child);
            } else {//存放空间不够再新建一行
                currLine = new Line();
                mLines.add(currLine);
                currLine.addChild(child);
            }
        }
        //累加高度
        
        mContainerHeight = 0;
        
        for (int i = 0; i < mLines.size(); i++) {
            if (i != (mLines.size() - 1)) {
                mContainerHeight += mLines.get(i).getLineHeight() + mVerticalSpace;
            } else {
                mContainerHeight += mLines.get(i).getLineHeight();
            }
        }
        // 使用包裹内容的方式式把每一个元素计算出容器的宽与高,设置给当前容器
        setMeasuredDimension(mContainerWidth, mContainerHeight);
    }
    /*** 方法 二。摆放  left top bottom right 
    @param changed
    @param l
    @param t
    @param r
    @param b
    */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        int lineLeft=0;
        int lineTop=0;
        for(int i=0;i0)
            {
                //第二行开始top要累加
                lineTop+=mLines.get(i-1).getLineHeight()+mVerticalSpace;
            }
            //对每一行中的元素进行摆放
            List views = line.getViews();
            lineLeft=0;
            for(int index=0;index 0) {
                    // 本行中的第二个元素
                    lineLeft = views.get(index - 1).getRight() + mHorizonalSpace;
                }
                int cWidth = lineChild.getMeasuredWidth();
                int cHeight = lineChild.getMeasuredHeight();
                int mode=MeasureSpec.EXACTLY;//80+10 andoid_layoutWidth="90dp"
                //创建measure使用数值的方式 MODE+SIZE
                int measureWidth=MeasureSpec.makeMeasureSpec(cWidth+eachViewSpace, mode);
                lineChild.measure(measureWidth, 0);//0代表使用包裹获取宽高
                //摆放
                int cLeft=lineLeft;
                int cTop=lineTop;
                int cRight=cLeft+cWidth+eachViewSpace;
                int cBottom=cTop+cHeight;
                lineChild.layout(cLeft, cTop, cRight, cBottom);
            }
        }
    }
    /*** 方法 三。画图,一般不去重写
    @param canvas
    */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

}



你可能感兴趣的:(流式布局FlowLayout)