Android FlowLayout的实现

今天我来说下android如何实现流式布局。


image.png

先分析下如何实现这样的效果,首先肯定是要自定义一个ViewGroup
然后就是计算View的宽和高,如何获取宽高呢?参照最终效果来分析,

宽其实就是每一行宽中最大的一个,高就是每一行的高累加。

如何实现呢,代码走起。。。

package weight.uztek.customview;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

public class FlowLly extends ViewGroup {

    private List<List<View>> allViews = new ArrayList<>();

    //每行的宽度
    private List<Integer> widthList = new ArrayList<>();

    //每行的高度
    private List<Integer> heightList = new ArrayList<>();


    public FlowLly(Context context) {
        super(context);
    }

    public FlowLly(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FlowLly(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        allViews.clear();
        widthList.clear();
        heightList.clear();

        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        int width = 0;
        int height = 0;

        //行宽
        int lineWidth = 0;

        //行高
        int lineHeight = 0;

        measureChildren(widthMeasureSpec, heightMeasureSpec);

        int childCount = getChildCount();

        List<View> views = new ArrayList<>();//第一行的View

        for (int i = 0; i < childCount; i++) {

            View childView = getChildAt(i);
            MarginLayoutParams layoutParams = (MarginLayoutParams) childView.getLayoutParams();

            int childWidth = childView.getMeasuredWidth() + layoutParams.leftMargin + layoutParams.rightMargin;

            int childHeight = childView.getMeasuredHeight() + layoutParams.topMargin + layoutParams.bottomMargin;

            //判断是否抢换行
            if (lineWidth + childWidth > widthSize) {
                //换行
                widthList.add(lineWidth);
                heightList.add(lineHeight);
                lineWidth = childWidth;
                lineHeight = childHeight;
                allViews.add(views);
                views = new ArrayList<>();
                views.add(childView);
            } else {
                //在同一行
                lineWidth += childWidth;
                lineHeight = Math.max(lineHeight, childHeight);
                views.add(childView);
            }

            if(i==childCount-1){
                widthList.add(lineWidth);
                heightList.add(lineHeight);
                allViews.add(views);
            }

        }

        width = max(widthList);
        height = add(heightList);
        setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : width, heightMode == MeasureSpec.EXACTLY ? heightSize : height);
    }

    private int max(List<Integer> datas) {
        int max = datas.get(0);
        for (int i : datas) {
            if (i > max)
                max = i;
        }
        return max;
    }

    private int add(List<Integer> datas) {
        int result = 0;
        for (int i : datas) {
            result += i;
        }
        return result;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int height = 0;
        int width = 0;
        for (int i = 0; i < allViews.size(); i++) {

            for (View view : allViews.get(i)) {

                MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams();

                int left, top, right, bottom;

                left =  width + layoutParams.leftMargin;

                top =  height + layoutParams.topMargin;

                right = left + view.getMeasuredWidth();

                bottom = top + view.getMeasuredHeight();

                width += view.getMeasuredWidth()+layoutParams.leftMargin+layoutParams.rightMargin;

                view.layout(left,top,right,bottom);

            }

            width=0;
            height += heightList.get(i);
        }
    }

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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容