android 自定义推送布局_Android 自定义流布局

一、来张图片看看实现的效果

feeb56c1fdc3e153764055f7ec94d932.png

二、上代码

1、布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="6dp"
        android:layout_marginRight="6dp"
        android:orientation="vertical">

    <TextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#e8e8e8"
            android:paddingLeft="10dp"
            android:paddingTop="5dp"
            android:paddingRight="10dp"
            android:paddingBottom="6dp"
            android:textColor="#000000" />
</LinearLayout>

2、自定义流布局

public class FlowLayout extends ViewGroup {

    private LayoutInflater mInflater;

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

    public FlowLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mInflater = LayoutInflater.from(getContext());
    }

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

        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
        int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
        int modeHeight = MeasureSpec.getMode(heightMeasureSpec);

        int count = getChildCount();
        int lineWidth = 0;
        int topHeight = 0;
        int maxWidth = 0;
        int paddingLeft = getPaddingLeft();
        int paddingRight = getPaddingRight();
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);

            // 测量子View的宽和高
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            // 得到LayoutParams
            MarginLayoutParams lp = (MarginLayoutParams) child
                    .getLayoutParams();
            // 子view的占据的宽度
            int childWidth = child.getMeasuredWidth() + lp.leftMargin
                    + lp.rightMargin;
            // 子view占据的高度
            int childHeight = child.getMeasuredHeight() + lp.topMargin
                    + lp.bottomMargin;

            if (lineWidth + childWidth > sizeWidth - paddingLeft - paddingRight) {
                //换行
                lineWidth = childWidth;
                topHeight += childHeight;

                //确保始终得到最大的宽度
                maxWidth = Math.max(maxWidth, lineWidth);
            } else {

                lineWidth += childWidth;

                //确保始终得到最大的宽度
                maxWidth = Math.max(maxWidth, lineWidth);
            }

            //最后一个
            if (i == count - 1) {
                topHeight += childHeight;
            }
        }

        setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth
                        : maxWidth + paddingLeft + paddingRight,
                modeHeight == MeasureSpec.EXACTLY ? sizeHeight : topHeight
                        + getPaddingTop() + getPaddingBottom());
    }

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

        int paddingLeft = getPaddingLeft();
        int paddingRight = getPaddingRight();
        int paddingTop = getPaddingTop();
        int width = getWidth();
        int lastLineTop = 0;
        int lastRight = 0;
        int lastBottom = 0;
        boolean firstLine=true;

        int count = getChildCount();
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);

            MarginLayoutParams lp = (MarginLayoutParams) child
                    .getLayoutParams();
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();

            int left = 0;
            int top = 0;
            int right = 0;
            int bottom = 0;

            if (lastRight+childWidth+lp.rightMargin > width + paddingRight) {
                //换行
                left = paddingLeft + lp.leftMargin;
                top = lastBottom + lp.topMargin;

                lastLineTop=lastBottom;

                firstLine=false;
            } else {
                //未换行
                left = lastRight + lp.leftMargin;
                if(firstLine){
                    top = paddingTop + lp.topMargin;
                }else {
                    top = lastLineTop+lp.topMargin;
                }

            }
            
            right = left + childWidth + lp.rightMargin;
            bottom = top + childHeight + lp.bottomMargin;

            // 为子view布局
            child.layout(left, top, right, bottom);
            lastRight = right;
            lastBottom = bottom;
        }
    }

    /**
     * 默认返回的LayoutParams
     */
    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    public void initData(List<String> list) {

        int count = list.size();
        for (int i = 0; i < count; i++) {
            View view = mInflater.inflate(R.layout.fl_tv, this,
                    false);
            final TextView tv = (TextView) view.findViewById(R.id.tv);
            tv.setText(list.get(i));

            this.addView(view);
        }
    }
}

3、使用

<com.ay30.flowlayout.FlowLayout
            android:layout_height="wrap_content"
            android:id="@+id/flowLayout"
            android:layout_width="match_parent"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp" />

测试数据

        FlowLayout flowLayout=findViewById(R.id.flowLayout);
        
        List<String> qualiNameList = new ArrayList<>();
        qualiNameList.add("身份证");
        qualiNameList.add("道路运输证");
        qualiNameList.add("行驶证");
        qualiNameList.add("驾驶证");
        qualiNameList.add("从业资格证");
        qualiNameList.add("押运员证");
        qualiNameList.add("安全员证");
        qualiNameList.add("营业执照");
        qualiNameList.add("道路运输许可证");
        qualiNameList.add("道路运输许可证(车挂)");
        qualiNameList.add("行驶证(车挂)");
        qualiNameList.add("罐检合格证");

        flowLayout.initData(qualiNameList);

四、心得

1、想清楚了还是简单,一开始一直不对,后面就先按一个一个搞,像给一面墙贴瓷砖一样。以后遇到这种类似的问题就可以套用同样的模型了。

2、get到重点;测量(onMeasure)与布局(onLayout);

3、数据结构和算法很重要,可以锻炼思维,可以快速知道什么问题用什么算法,而且还不需要怀疑或验证是错的,因为大神或大师已经验证过了;这也是学数学、学算法、学数据结构的目的吧。这才是与计算机沟通的思维。

4、看大神写的代码,可以快速知道怎么实现最好;就好比写文章,你首先要有一定的积累,才能出口成章,快速写完一篇好文章。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值