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);
    }
}

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容