Android瀑布流实现二

public class FlowView extends ViewGroup {
    // 用来记录描述有多少行View
    private List<LineView> mLineViews = new ArrayList<LineView>();
    // 用来记录当前已经添加到了哪一行
    private LineView mCurrentLineView;
    private int mHorizontalSpace = 20;//水平间隔
    private int mVerticalSpace = 20;//垂直间隔

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

    public FlowView(Context context) {
        this(context, null);
    }

    /**
     * 向外公布的方法
     * @param horizontalSpace
     * @param VerticalSpace
     */
    public void setSpace(int horizontalSpace, int VerticalSpace){
        this.mHorizontalSpace = horizontalSpace;
        this.mVerticalSpace = VerticalSpace;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // 给Child 布局---> 给Line布局
        int paddingLeft = getPaddingLeft();
        int paddingTop = getPaddingTop();
        for (int i = 0; i < mLineViews.size(); i++) {
            LineView lineView = mLineViews.get(i);
            //给每个lineViewlayout即可
            lineView.layout(paddingLeft, paddingTop);
            //表示下一行的高度
            paddingTop += mVerticalSpace + lineView.mHeight;
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //清空
        mLineViews.clear();
        mCurrentLineView = null;

        //获得布局的宽度
        int layoutWidth = MeasureSpec.getSize(widthMeasureSpec);
        //获取行最大的宽度
        int maxWidth = layoutWidth - getPaddingLeft() - getPaddingRight();
        // 测量孩子
        int count = getChildCount();
        for (int i = 0; i < count; i++) {
            View view = getChildAt(i);

            //如果孩子不可见,就不必测量
            if (view.getVisibility() == View.GONE) {
                continue;
            }
            //测量孩子
            measureChild(view, widthMeasureSpec, heightMeasureSpec);

            //子行添加view
            if (mCurrentLineView == null) {
                mCurrentLineView = new LineView(maxWidth, mHorizontalSpace);
                //添加到行中
                mLineViews.add(mCurrentLineView);

                //航中一个孩子没有
                mCurrentLineView.addView(view);
            }else {
                //行不空,说明有孩子
                if (mCurrentLineView.canAdd(view)) {
                    // 可以添加
                    mCurrentLineView.addView(view);
                }else {
                    //添加不下去,换行添加
                    mCurrentLineView = new LineView(maxWidth, mHorizontalSpace);
                    //添加到集合
                    mLineViews.add(mCurrentLineView);
                    // 将view添加到line
                    mCurrentLineView.addView(view);
                }
            }
        }
        //super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //设置自己的宽度与高度
        int measuredWidth = layoutWidth;
        float allHeight = 0;
        for (int i = 0; i < mLineViews.size(); i++) {
            float height = mLineViews.get(i).mHeight;
            // 加行高
            allHeight += height;
            if (i != 0) {
                // 加间距
                allHeight += mVerticalSpace;
            }
        }
        int measuredHeight = (int) (getPaddingBottom() + getPaddingTop() + allHeight + 0.5f);
        //测量自身的高度
        setMeasuredDimension(measuredWidth, measuredHeight);
    }

    class LineView {
        public List<View> mViews = new ArrayList<View>();// 用来记录每一行有几个View
        public int mUsedWidth;//已使用的宽度
        public int mMaxWidth;//最大宽度
        public int mHorizontalSpace; View和view之间的水平间距
        public int mHeight;//高度
        public int mMaginLeft;
        public int mMaginBottom;
        public int mMaginRight;
        public int mMaginTop;

        public LineView(int maxWidth, int space){
            this.mMaxWidth = maxWidth;
            this.mHorizontalSpace = space;
        }

        /**
         * 给孩子布局
         * 
         * @param paddingLeft
         * @param paddingTop
         */
        public void layout(int paddingLeft, int paddingTop) {
            int currentLeft = paddingLeft;

            //把剩余的空间评分
            float extra = 0;
            float widthAvg = 0;
            int size = mViews.size();
            // 判断已经使用的宽度是否小于最大的宽度
            if (mMaxWidth > mUsedWidth) {
                extra = mMaxWidth - mUsedWidth;
                widthAvg = extra / size;
            }

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

                View view = mViews.get(i);
                int viewWidth = view.getMeasuredWidth();
                int viewHeight = view.getMeasuredHeight();

                // 判断是否有富余
                if (widthAvg != 0) {
                    int newWidth = (int) (viewWidth + widthAvg + 0.5f);
                    int widthMeasureSpec = MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY);
                    int heightMeasureSpec = MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.EXACTLY);
                    view.measure(widthMeasureSpec, heightMeasureSpec);
                    //重新赋值
                    viewWidth = view.getMeasuredWidth();
                    viewHeight = view.getMeasuredHeight();
                }
                // 布局
                int left = currentLeft;
                //int top = paddingTop;
                //让子view垂直居中
                int top = (int) (paddingTop + (mHeight - viewHeight)/2.0f + 0.5f);
                int right = left + viewWidth;
                int bottom = top + viewHeight;
                view.layout(left, top, right, bottom);
                //下一个view的left
                currentLeft += viewWidth + mHorizontalSpace;
            }
        }

        /**
         * 添加view
         * @param view
         */
        public void addView(View view){
            int size = mViews.size();
            int viewWidth = view.getMeasuredWidth();
            int viewHeight = view.getMeasuredHeight();
            //mUsedWidth += viewWidth;
            if (size == 0) {
                // 说还没有添加View
                if (viewWidth > mMaxWidth) {
                    mUsedWidth = mMaxWidth;
                }else {
                    mUsedWidth = viewWidth;
                }
                //初始化高度
                mHeight = viewHeight;
            }else {
                // 多个view的情况
                mUsedWidth += viewWidth + mHorizontalSpace;
                //如果当前的高度》最新加入view的高度,就是当前的高度,否则就是行加入的view的高度
                mHeight = mHeight > viewHeight ? mHeight : viewHeight;
            }
            // 将View记录到集合中
            mViews.add(view);


        }

        /**
         * 能否添加
         * @param view
         * @return
         */
        public boolean canAdd(View view){
            //如果没有view,就可添加
            if (mViews.size() == 0) {
                return true;
            }

            int viewWidth = view.getMeasuredWidth();
            if (mUsedWidth + mHorizontalSpace + viewWidth > mMaxWidth) {
                // 加不进去
                return false;
            }else {
                return true;
            }
        }
    }



}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lovoo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值