美文网首页
自定义流式布局

自定义流式布局

作者: 慢游的海牛 | 来源:发表于2020-03-10 15:42 被阅读0次

    文章目的:实现流式布局的效果,明白view的绘制流程

    运行软件和环境:
    • android Studio 3.5.1
    • jdk1.8
    效果图
    11.jpg
    自定义viewgroup

    自定义viewgroup对子view进行测量和布局

    代码
    /**
     * author : Luuuzi
     * e-mail : wang1143303@163.com
     * date   : 2020/2/26 0026 11:10
     * desc   : 自定义流式布局
     */
    public class FlowLayout extends ViewGroup {
        private String tag = getClass().getSimpleName();
        private float dashWDefine = 0;//子view默认宽间距
        private float dashHDefine = 0;//子view默认高间距
    
        private ArrayList<ArrayList<View>> viewLines = null;
        private ArrayList<Integer> viewHs = null;
    
        public FlowLayout(Context context) {
            super(context);
        }
    
        public FlowLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        private void initMeasure() {
            if (viewLines == null) {
                viewLines = new ArrayList<>();
            } else {
                viewLines.clear();
            }
            if (viewHs == null) {
                viewHs = new ArrayList<>();
            } else {
                viewHs.clear();
            }
            dashWDefine = 20;
            dashHDefine = 30;
        }
    
        /**
         * @param widthMeasureSpec
         * @param heightMeasureSpec
         */
        @SuppressLint("DrawAllocation")
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    //        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            Log.i(tag, "onMeasure:");
            initMeasure();
            int pWMode = MeasureSpec.getMode(widthMeasureSpec);
            int pHMode = MeasureSpec.getMode(heightMeasureSpec);
            int pWSize = MeasureSpec.getSize(widthMeasureSpec);
            int pHSize = MeasureSpec.getSize(heightMeasureSpec);
    
            int currentUsedW = getPaddingLeft() + getPaddingRight();//记录已经用掉的宽度
            //测量子view
            int childCount = getChildCount();
            for (int i = 0; i < childCount; i++) {
                View childAt = getChildAt(i);
                LayoutParams childLp = childAt.getLayoutParams();
    
                int childWMS = getChildMeasureSpec(widthMeasureSpec, getPaddingLeft() + getPaddingRight(), childLp.width);
                int childHMS = getChildMeasureSpec(heightMeasureSpec, getPaddingTop() + getPaddingBottom(), childLp.height);
                childAt.measure(childWMS, childHMS);
    
                //测量摆放空间(将子view 分行存储)
                if (viewLines.isEmpty() || currentUsedW + childAt.getMeasuredWidth() + dashWDefine > pWSize) {//新的一行
                    ArrayList<View> views = new ArrayList<>();
    
                    views.add(childAt);
                    viewLines.add(views);
                    viewHs.add(childAt.getMeasuredHeight());//存高度
    
                    currentUsedW = getPaddingLeft() + getPaddingRight() + childAt.getMeasuredWidth() + (int) dashWDefine;
    
                } else {//同一行
                    viewLines.get(viewLines.size() - 1).add(childAt);
                    //存一行中的最大高度
                    viewHs.set(viewHs.size() - 1, viewHs.get(viewHs.size() - 1) > childAt.getMeasuredHeight() ? viewHs.get(viewHs.size() - 1) : childAt.getMeasuredHeight());
                    currentUsedW += childAt.getMeasuredWidth() + dashWDefine;
                }
            }
    
            //测量自己
            int meW;
            int meH;
    //        if (pWMode == MeasureSpec.EXACTLY) {
    //            meW = pWSize;
    //        } else {
            meW = getCurrentMaxLineW();
    //        }
    //        if (pHMode == MeasureSpec.EXACTLY) {
    //            meH = pHSize;
    //        } else {
            meH = getcountChildHeight();
    //        }
            setMeasuredDimension(meW, meH);
        }
    
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            if (viewLines == null || viewHs == null) {
                return;
            }
            int curTop = getPaddingTop();//view布局所对应的top坐标
    
            for (int i = 0; i < viewHs.size(); i++) {//一行一行开始摆放
                int curLeft = getPaddingLeft();//view布局所对应的left坐标
                curTop += i == 0 ? 0 : viewHs.get(i - 1) + dashHDefine;
                ArrayList<View> views = viewLines.get(i);
                for (int j = 0; j < views.size(); j++) {//对每行子view进行布局
                    View child = views.get(j);
                    child.layout(curLeft, curTop, curLeft + child.getMeasuredWidth(), curTop + child.getMeasuredHeight());
                    curLeft += child.getMeasuredWidth() + dashWDefine;
                }
            }
        }
    
        // 获取所有行的最大宽度
        private int getCurrentMaxLineW() {
            if (viewLines.isEmpty()) {
                return 0;
            } else {
                int max = 0;
                for (int i = 0; i < viewLines.size(); i++) {
                    ArrayList<View> views = viewLines.get(i);
                    int w = 0;
                    for (int j = 0; j < views.size(); j++) {
                        w += views.get(j).getMeasuredWidth() + (int) dashWDefine;
                    }
                    max = Math.max(w, max);
                }
                return max + getPaddingLeft() + getPaddingRight();
            }
        }
    
        private int getcountChildHeight() {
            if (viewHs.isEmpty()) {
                return 0;
            } else {
                int h = 0;
                for (int i = 0; i < viewHs.size(); i++) {
                    h += viewHs.get(i) + dashHDefine;
                }
                return h + getPaddingTop() + getPaddingBottom();
            }
        }
    }
    
    使用
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#fff"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
        <com.luuuzi.demo003.widget.FlowLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#fff">
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="苹果7手机壳"
                android:textColor="#f00"
                android:textSize="15sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="道德经"
                android:textColor="#f00"
                android:textSize="16sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="美甲套装初学者家用"
                android:textColor="#f00"
                android:textSize="15sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="阿玛尼"
                android:textColor="#f00"
                android:textSize="25sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="破壁机加热全自动"
                android:textColor="#f00"
                android:textSize="18sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="华为mate30"
                android:textColor="#f00"
                android:textSize="12sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="全自动洗衣机"
                android:textColor="#f00"
                android:textSize="10sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="i5-9400f"
                android:textColor="#f00"
                android:textSize="15sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="巨坑"
                android:textColor="#f00"
                android:textSize="13sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="安卓插件化"
                android:textColor="#f00"
                android:textSize="17sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="小米10"
                android:textColor="#f00"
                android:textSize="15sp" />
        </com.luuuzi.demo003.widget.FlowLayout>
    
        <androidx.appcompat.widget.AppCompatTextView
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:text="搜索历史"
            android:gravity="center_vertical"/>
        <com.luuuzi.demo003.widget.FlowLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#fff">
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="iphone XS"
                android:textColor="#f00"
                android:textSize="15sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="老子"
                android:textColor="#f00"
                android:textSize="16sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="美甲套装初学者家用"
                android:textColor="#f00"
                android:textSize="15sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="雅诗兰黛"
                android:textColor="#f00"
                android:textSize="25sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="九阳豆浆"
                android:textColor="#f00"
                android:textSize="18sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="华为mate30"
                android:textColor="#f00"
                android:textSize="12sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="全自动洗衣机"
                android:textColor="#f00"
                android:textSize="10sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="i5-9400f"
                android:textColor="#f00"
                android:textSize="15sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="巨坑"
                android:textColor="#f00"
                android:textSize="13sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="戴尔电脑"
                android:textColor="#f00"
                android:textSize="17sp" />
    
            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_key"
                android:padding="10dp"
                android:text="小米10pro"
                android:textColor="#f00"
                android:textSize="15sp" />
        </com.luuuzi.demo003.widget.FlowLayout>
    </LinearLayout>
    
    完成

    项目地址:Demo003

    相关文章

      网友评论

          本文标题:自定义流式布局

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