学习篇---FlowLayout的实现

FlowLayout,通过自定义ViewGroup来实现,主要重写的onMeasure()和onLayout()方法;onMeasure()作用是计算自定义ViewGroup中控件的大小,从而确定自定义布局的with和height。onLayout()作用是对自定义ViewGroupz中的控件进行定位。

效果图:

FlowLayout.java:

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) {

        int layoutWithSize = MeasureSpec.getSize(widthMeasureSpec);
        int layoutWithMode = MeasureSpec.getMode(widthMeasureSpec);
        int layoutHeightSize = MeasureSpec.getSize(heightMeasureSpec);
        int layoutHeightMode = MeasureSpec.getMode(heightMeasureSpec);
        int layoutWith = 0;
        int layoutHeight = 0;
        int lineWith = 0;
        int lineHeight = 0;

        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
            MarginLayoutParams marginLayoutParams = (MarginLayoutParams) getChildAt(i).getLayoutParams();
            int childWith = getChildAt(i).getMeasuredWidth() + marginLayoutParams.rightMargin + marginLayoutParams.leftMargin;
            int childHeight = getChildAt(i).getMeasuredHeight() + marginLayoutParams.topMargin + marginLayoutParams.bottomMargin;
            if (lineWith + childWith > layoutWithSize-getPaddingLeft()-getPaddingRight()) {
                layoutWith = Math.max(layoutWith, lineWith);
                lineWith = childWith;
                layoutHeight += lineHeight;
                lineHeight = childHeight;
            } else {
                lineWith += childWith;
                lineHeight = Math.max(lineHeight, childHeight);
            }
            if (i == childCount - 1) {
                layoutHeight += lineHeight;
                layoutWith = Math.max(layoutWith, childWith);
            }

        }

        Log.e("layoutHeight", layoutHeight + "");
        Log.e("layoutWith", layoutWith + "");
        Log.e("layoutWithSize", layoutWithSize + "");

        setMeasuredDimension(layoutWithMode == MeasureSpec.EXACTLY ? layoutWithSize : layoutWith+getPaddingLeft()+getPaddingRight(), layoutHeightMode == MeasureSpec.EXACTLY ? layoutHeightSize : layoutHeight+getPaddingTop()+getPaddingBottom());


    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    //存放每行的高
    private List<Integer> lineHeightList = new ArrayList<>();
    //存放每行view的list的list
    private List<List<View>> allViews= new ArrayList<>();

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        lineHeightList.clear();
        allViews.clear();
        int lineHeght = 0;
        int lineWith = 0;
        List<View> lineViews = new ArrayList<>();
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            MarginLayoutParams marginLayoutParams = (MarginLayoutParams) child.getLayoutParams();
            int childHeight = child.getMeasuredHeight();
            int childWith = child.getMeasuredWidth();
            if (lineWith + childWith + marginLayoutParams.leftMargin + marginLayoutParams.rightMargin > getWidth()-getPaddingLeft()-getPaddingRight()) {
                lineHeightList.add(lineHeght);
                allViews.add(lineViews);
                lineViews = new ArrayList<>();
                lineWith = 0;
                lineHeght = childHeight + marginLayoutParams.topMargin + marginLayoutParams.bottomMargin;
            }
            lineWith += childWith + marginLayoutParams.leftMargin + marginLayoutParams.rightMargin;
            lineHeght = Math.max(lineHeght, childHeight + marginLayoutParams.topMargin + marginLayoutParams.bottomMargin);
            lineViews.add(child);

        }
        lineHeightList.add(lineHeght);
        allViews.add(lineViews);

        int lineNum = allViews.size();
        int left=getPaddingLeft();
        int top=getPaddingTop();
        for (int i = 0; i < lineNum; i++)
        {
            // 当前行的所有的View
            lineViews = allViews.get(i);
            lineHeght = lineHeightList.get(i);

            for (int j = 0; j < lineViews.size(); j++)
            {
                View child = lineViews.get(j);
                // 判断child的状态
                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();

                // 为子View进行布局
                child.layout(lc, tc, rc, bc);

                left += child.getMeasuredWidth() + lp.leftMargin
                        + lp.rightMargin;
            }
            left = getPaddingLeft();
            top += lineHeght ;
        }


    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值