16—03—08 (笔记 一 )

   

   一、项目中用到流布局 总结  参考于:http://blog.csdn.net/jdsjlzx/article/details/45042081?ref=myread

项目中需要用到搜索标签,需要根据每个标签的大小使布局自适应

首先想要自定义一个可包含不同大小长度的布局,就需要继承自viewGroup,重写其两个重要方法


1、重写onMeasure()方法,用于将此布局中包含的所有控件进行测量,同时测量出该流布局的宽和高

//测量子控件的总长度和高度
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // 清空数据集合
        childViewList.clear();
        lineHeightList.clear();
        // 获取子view的数量
        int childCount = getChildCount();
        //获取容器的宽和高
        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
        // 每一行的实际宽和高
        int lineWidth = 0;
        int lineHeight = 0;
        // 实际测量出的容器的宽和高
        int width = 0;
        int height = 0;
        // 创建存放每一行子view的集合
        List<View> viewList = new ArrayList<View>();
        for (int i = 0; i < childCount; i++) {
            // 测量每一个子view
            View childView = getChildAt(i);
            // 对子view进行测量
            measureChild(childView, widthMeasureSpec, heightMeasureSpec);
            // 获取到边距参数
            MarginLayoutParams mlp = (MarginLayoutParams) childView.getLayoutParams();
            // 计算出子view占据的宽度和高度
            int childWidth = childView.getMeasuredWidth() + mlp.leftMargin + mlp.rightMargin;
            int childHeight = childView.getMeasuredHeight() + mlp.topMargin + mlp.bottomMargin;
            // 如果当前行的宽度加上当前这个子view的宽度大于了容器的宽度,需要换行
            if (lineWidth + childWidth > parentWidth) {
                // 保存这一行的数据
                childViewList.add(viewList);
                // 保存行高
                lineHeightList.add(lineHeight);
                // 保存这一行的行宽
                width = Math.max(width, lineWidth);
                // 重置行宽,换行后,当前子view的宽度即为下一行的其实宽度
                lineWidth = childWidth;
                // 记录容器的行高
                height += lineHeight;
                // 重置行高
                lineHeight = childHeight;
                // 重置view集合
                viewList = new ArrayList<View>();
            } else {
                // 如果未换行的情况

                // 添加这一行的子view到集合
                viewList.add(childView);
                // 叠加行宽
                lineWidth += childWidth;
                // 得到这一行的最大行高
                lineHeight = Math.max(lineHeight, childHeight);
            }

            if (i == childCount - 1) {
                // 将最后一行数据添加进集合
                viewList.add(childView);
                childViewList.add(viewList);
                lineHeightList.add(lineHeight);
                // 处理最后一个子view,容器总宽度取测量最大宽度和当前行宽度的最大值
                width = Math.max(width, lineWidth);

                // 高度叠加
                height += lineHeight;
            }

        }
        // 取出容器宽和高的测量模式
        int parentWidthMode = MeasureSpec.getMode(widthMeasureSpec);
        int parentHeightMode = MeasureSpec.getMode(heightMeasureSpec);
        // 设置容器的测量尺寸,如果宽度的测量模式为精确测量,则将容器本身的宽和高作为尺寸
        // 否则,将我们动态测量的宽和高作为容器的尺寸
        setMeasuredDimension(parentWidthMode == MeasureSpec.EXACTLY ? parentWidth : width,
                parentHeightMode == MeasureSpec.EXACTLY ? parentHeight : height);
       // super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
测量出每一行的宽度和高度,并将每行的子view添加到集合中,注意在处理最后一个子view时,要根据是否是单独一行来计算出高度和宽度,并且若换行了,则需要

再添加一行view到集合中

setMeasureDimension()方法是测量最后需要调用的方法,用于将测量的值设置给控件,是onMeasure方法最后要进行的一步,若手动调用了此方法,并且把控件

的宽高值交给父类的onMeasure方法进行测量了,会导致我们手动设置的宽高值失效。


2、重写onLayout()方法对布局内的子控件进行布局

 // 对子控件进行布局
    @Override
    protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
        // 设置子view的位置
        int left = 0;
        int top = 0;
        // 获取到容器中view的行数
        int lineCount = childViewList.size();

        for (int j = 0; j < lineCount; j++) {
            // 取出当前行的view集合
            List<View> views = childViewList.get(j);
            // 获取当前行的高度
            int lineHeight = lineHeightList.get(j);
            for (int l = 0; l < views.size(); l++) {
                // 获取当前行的每一个view
                View view = views.get(l);
                // 判断当前view是否显示
                if (view.getVisibility() == View.GONE) {
                    continue;
                }
                // 得到当前view的上,下,左,右位置
                MarginLayoutParams childMlp = (MarginLayoutParams) view.getLayoutParams();
                int childLeft = left + childMlp.leftMargin;
                int childRight = childLeft + view.getMeasuredWidth();
                int childTop = top + childMlp.topMargin;
                int childBottom = childTop + view.getMeasuredHeight();

                // 对该view进行布局
                view.layout(childLeft, childTop, childRight, childBottom);
                // 左边距离叠加
                left += view.getMeasuredWidth() + childMlp.leftMargin + childMlp.rightMargin;
            }

            // 下一行,重置左边距,叠加上边距
            left = 0;
            top += lineHeight;
        }

    }

计算子控件的位置,需要得出控件的left,top和控件的宽度和高度即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值