Custom flow layout

public class MyFlowView extends ViewGroup {
    public MyFlowView(Context context) {
        this(context,null);
    }
    public MyFlowView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }
    public MyFlowView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    //Measure
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //Total width and height
        int width=0 ;
        int height=0;
        //Record the width and height of each line
        int lineWidth=0;
        int lineHeight=0;
        //宽度相关
        int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
        //高度相关
        int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
        for (int i=0;i<getChildCount();i++){
            View childAt = getChildAt(i);
            //测量子view的宽和高
            measureChild(childAt,widthMeasureSpec,heightMeasureSpec);
            //得到LayoutParms
            MarginLayoutParams lp= (MarginLayoutParams) childAt.getLayoutParams();
            //Get the width and height of the child view
            int childWidth = childAt.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;
            int childHeight = childAt.getMeasuredHeight()+lp.topMargin+lp.bottomMargin;
            //Wrap
            if(lineWidth+ childWidth>sizeWidth-getPaddingLeft()-getPaddingRight()){
                //Contrast to get the maximum width
                width=Math.max(width,lineWidth);
                //Reset line width
                lineWidth=childWidth;
                //Accumulated height
                height+=lineHeight;
                // Reset line height
                lineHeight=childHeight;
            }else{
                //Overlay line width
                lineWidth+=childWidth;
                //得到最大行高
                lineHeight=Math.max(lineHeight,childHeight);
            }
            if(i==getChildCount()-1){
                width=Math.max(width,lineWidth);
                height+=lineHeight;
            }
        }
        switch (modeWidth){
            case MeasureSpec.EXACTLY:
                    width=sizeWidth;
                    break;
            case MeasureSpec.AT_MOST:
                    width+=getPaddingLeft()+getPaddingRight();
                    break;
            case MeasureSpec.UNSPECIFIED:
                    break;
        }
        switch (modeHeight){
            case MeasureSpec.EXACTLY:
                height=sizeHeight;
                break;
            case MeasureSpec.AT_MOST:
                height+=getPaddingTop()+getPaddingBottom();
                break;
            case MeasureSpec.UNSPECIFIED:
                break;
        }
        setMeasuredDimension(width,height) ;
    }


    //Store all views according to the view of each row to store
    private List<List<View>> mAllViews=new ArrayList();
    //Store the height of each row
    private List<Integer> mLineHeight=new ArrayList<Integer> ();
    //layout
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        mAllViews.clear();
        mLineHeight.clear();
        //得到当前ViewGroup的宽度
        int width=getWidth();
        int lineWidth=0;
        int lineHeight=0;
        List<View> lineViews=new ArrayList<>();
        for (int i=0;i<getChildCount();i++){
            View child = getChildAt(i);
            MarginLayoutParams lp= (MarginLayoutParams) child.getLayoutParams();
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();
            if(childWidth+lineWidth+lp.leftMargin+lp.rightMargin>width-getPaddingLeft()-getPaddingRight()){
                    mLineHeight.add(lineHeight);
                    mAllViews.add(lineViews);
                    //重置行宽
                    lineWidth=0;
                    lineHeight=childHeight+lp.topMargin+lp.bottomMargin;
                    lineViews=new ArrayList<>();
            }
            lineWidth+=childWidth+lp.leftMargin+lp.rightMargin;
            lineHeight=Math.max(lineHeight,childHeight+lp.topMargin+lp.bottomMargin);
            lineViews.add(child);
        }
        //处理最后一行
        mLineHeight.add(lineHeight);
        mAllViews.add(lineViews);

        //Set the position of the child view
        int left=getPaddingLeft();
        int top=getPaddingTop();

        for (int i=0;i<mAllViews.size();i++){
            //Get the current Line height and view
            lineViews = mAllViews.get(i);
            lineHeight=mLineHeight.get(i);


            for (int j=0;j<lineViews.size();j++){
                View child = lineViews.get(j) ;
                // Judge the visibility
                if(child.getVisibility()==View.GONE){
                    continue;
                }
                MarginLayoutParams lp= (MarginLayoutParams) child.getLayoutParams();
                int lc=left+lp.leftMargin;
                int tc=top+lp.topMargin;
                int rc=lc+child.getMeasuredWidth();
                int bc=tc+child.getMeasuredHeight();

                child.layout(lc,tc,rc,bc);
                left+=child.getMeasuredWidth( )+lp.leftMargin+lp.rightMargin;
            }
            left=getPaddingLeft();
            top+=lineHeight;
        }
    }


    /**
     * This method is mainly called when the parent container adds a child View
     to generate a type that matches this container Layout parameter class.
     * @param attrs
     * @return
     */
    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(),attrs);
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325185744&siteId=291194637