美文网首页
flowlayout

flowlayout

作者: 遇见开始遇见 | 来源:发表于2021-06-09 14:53 被阅读0次

    package com.example.flowlayout;

    import android.content.Context;

    import android.content.res.Resources;

    import android.graphics.Canvas;

    import android.util.AttributeSet;

    import android.util.Log;

    import android.util.TypedValue;

    import android.view.View;

    import android.view.ViewGroup;

    import java.util.ArrayList;

    import java.util.List;

    public class FlowLayout extends ViewGroup {

        private static final String TAG = "FlowLayout";

        private int mHorizontalSpacing = dp2px(16); //每个item横向间距

        private int mVerticalSpacing = dp2px(8); //每个item横向间距

        private List<List<View>> allLines = new ArrayList<>(); // 记录所有的行,一行一行的存储,用于layout

        List<Integer> lineHeights = new ArrayList<>(); // 记录每一行的行高,用于layout

        public FlowLayout(Context context) {

            super(context);

    //        initMeasureParams();

        }

        //反射

        public FlowLayout(Context context, AttributeSet attrs) {

            super(context, attrs);

    //        initMeasureParams();

        }

        //主题style

        public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {

            super(context, attrs, defStyleAttr);

    //        initMeasureParams();

        }

        //四个参数 自定义属性

        private void clearMeasureParams() {

            allLines.clear();

            lineHeights.clear();

        }

        //度量

        @Override

        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

            clearMeasureParams();//内存 抖动

            //先度量孩子

            int childCount = getChildCount();

            int paddingLeft = getPaddingLeft();

            int paddingRight = getPaddingRight();

            int paddingTop = getPaddingTop();

            int paddingBottom = getPaddingBottom();

            int selfWidth = MeasureSpec.getSize(widthMeasureSpec);  //ViewGroup解析的父亲给我的宽度

            int selfHeight = MeasureSpec.getSize(heightMeasureSpec); // ViewGroup解析的父亲给我的高度

            List<View> lineViews = new ArrayList<>(); //保存一行中的所有的view

            int lineWidthUsed = 0; //记录这行已经使用了多宽的size

            int lineHeight = 0; // 一行的行高

            int parentNeededWidth = 0;  // measure过程中,子View要求的父ViewGroup的宽

            int parentNeededHeight = 0; // measure过程中,子View要求的父ViewGroup的高

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

                View childView = getChildAt(i);

                LayoutParams childLP = childView.getLayoutParams();

                if (childView.getVisibility() != View.GONE) {

                    //将layoutParams转变成为 measureSpec

                    int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight,

                            childLP.width);

                    int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, paddingTop + paddingBottom,

                            childLP.height);

                    childView.measure(childWidthMeasureSpec, childHeightMeasureSpec);

                    //获取子view的度量宽高

                    int childMesauredWidth = childView.getMeasuredWidth();

                    int childMeasuredHeight = childView.getMeasuredHeight();

                    //如果需要换行

                    if (childMesauredWidth + lineWidthUsed + mHorizontalSpacing > selfWidth) {

                        //一旦换行,我们就可以判断当前行需要的宽和高了,所以此时要记录下来

                        allLines.add(lineViews);

                        lineHeights.add(lineHeight);

                        parentNeededHeight = parentNeededHeight + lineHeight + mVerticalSpacing;

                        parentNeededWidth = Math.max(parentNeededWidth, lineWidthUsed + mHorizontalSpacing);

                        lineViews = new ArrayList<>();

                        lineWidthUsed = 0;

                        lineHeight = 0;

                    }

                    // view 是分行layout的,所以要记录每一行有哪些view,这样可以方便layout布局

                    lineViews.add(childView);

                    //每行都会有自己的宽和高

                    lineWidthUsed = lineWidthUsed + childMesauredWidth + mHorizontalSpacing;

                    lineHeight = Math.max(lineHeight, childMeasuredHeight);

                    //处理最后一行数据

                    if (i == childCount - 1) {

                        allLines.add(lineViews);

                        lineHeights.add(lineHeight);

                        parentNeededHeight = parentNeededHeight + lineHeight + mVerticalSpacing;

                        parentNeededWidth = Math.max(parentNeededWidth, lineWidthUsed + mHorizontalSpacing);

                    }

                }

            }

            //再度量自己,保存

            //根据子View的度量结果,来重新度量自己ViewGroup

            // 作为一个ViewGroup,它自己也是一个View,它的大小也需要根据它的父亲给它提供的宽高来度量

            int widthMode = MeasureSpec.getMode(widthMeasureSpec);

            int heightMode = MeasureSpec.getMode(heightMeasureSpec);

            int realWidth = (widthMode == MeasureSpec.EXACTLY) ? selfWidth: parentNeededWidth;

            int realHeight = (heightMode == MeasureSpec.EXACTLY) ?selfHeight: parentNeededHeight;

            setMeasuredDimension(realWidth, realHeight);

        }

        //布局

        @Override

        protected void onLayout(boolean changed, int l, int t, int r, int b) {

            int lineCount = allLines.size();

            int curL = getPaddingLeft();

            int curT = getPaddingTop();

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

                List<View> lineViews = allLines.get(i);

                int lineHeight = lineHeights.get(i);

                for (int j = 0; j < lineViews.size(); j++){

                    View view = lineViews.get(j);

                    int left = curL;

                    int top =  curT;

    //                int right = left + view.getWidth();

    //                int bottom = top + view.getHeight();

                    int right = left + view.getMeasuredWidth();

                    int bottom = top + view.getMeasuredHeight();

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

                    curL = right + mHorizontalSpacing;

                }

                curT = curT + lineHeight + mVerticalSpacing;

                curL = getPaddingLeft();

            }

        }

    //    @Override

    //    protected void onDraw(Canvas canvas) {

    //        super.onDraw(canvas);

    //    }

        public static int dp2px(int dp) {

            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().getDisplayMetrics());

        }

     

    相关文章

      网友评论

          本文标题:flowlayout

          本文链接:https://www.haomeiwen.com/subject/tkyeeltx.html