仿b站发现界面关键字的FlowLayout.

来源:互联网 发布:淘宝客户关系管理打折 编辑:程序博客网 时间:2024/05/16 12:52

这段时间想做个仿b站的程序,现在完成了整个界面。一点一点分享出来。
文章开头,感谢鸿洋大神的轮子。(http://blog.csdn.net/lmj623565791/article/details/38352503)
在此基础上改动了一些,觉得更易懂。
1.FlowLayout
这里只贴了onMeasure()和onLayout()方法。具体可以去看鸿洋大神的。

    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        // 获得它的父容器为它设置的测量模式和大小        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);        int modeWidth = MeasureSpec.getMode(widthMeasureSpec);        int modeHeight = MeasureSpec.getMode(heightMeasureSpec);        // 如果是warp_content情况下,记录宽和高        int width = 0;        int height = 0;        /**         * 记录每一行的宽度,width不断取最大宽度         */        int lineWidth = 0;        /**         * 每一行的高度,累加至height         */        int lineHeight = 0;        int cCount = getChildCount();        //遍历        for (int i = 0; i < cCount; i++) {            View child = getChildAt(i);            // 测量每一个child的宽和高            measureChild(child, widthMeasureSpec, heightMeasureSpec);            // 得到child的lp            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();            // 当前子空间实际占据的宽度            int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;            // 当前子空间实际占据的高度            int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;            /**             * 如果加入当前child,则超出最大宽度,则的到目前最大宽度给width,类加height 然后开启新行             */            if (lineWidth + childWidth > sizeWidth) {                width = Math.max(lineWidth, childWidth);                lineWidth = childWidth;// 重新开启新行,开始记录                // 叠加当前高度                height += lineHeight;                // 开启记录下一行的高度                lineHeight = childHeight;            } else {// 否则累加值lineWidth,lineHeight取最大高度                lineWidth += childWidth;                lineHeight = Math.max(lineHeight, childHeight);            }// 如果是最后一个,则将当前记录的最大宽度和当前lineWidth做比较            if (i == cCount - 1) {                width = Math.max(width, lineWidth);                height += lineHeight;            }        }        setMeasuredDimension((modeWidth == MeasureSpec.EXACTLY) ? sizeWidth : width, (modeHeight == MeasureSpec.EXACTLY) ? sizeHeight : height);    }    /**     * 存储所有的View,按行记录     */    private List<List<View>> mAllViews = new ArrayList<List<View>>();    /**     * 记录每一行的最大高度     */    private List<Integer> mLineHeight = new ArrayList<Integer>();    @Override    protected void **onLayout**(boolean changed, int l, int t, int r, int b) {       mAllViews.clear();        mLineHeight.clear();        int width=getWidth();        int lineWidth = 0;        int lineHeight = 0;        // 存储每一行所有的childView        List<View> lineViews = new ArrayList<View>();        int cCount = getChildCount();        // 遍历        for (int i=0;i<cCount;i++){            View child=getChildAt(i);            MarginLayoutParams lp = (MarginLayoutParams) child                    .getLayoutParams();            int childWidth = child.getMeasuredWidth();            int childHeight = child.getMeasuredHeight();            // 如果已经需要换行            if (childWidth+lp.leftMargin+lp.rightMargin+lineWidth > width){                // 记录这一行所有的View以及最大高度                mLineHeight.add(lineHeight);                // 将当前行的childView保存,然后开启新的ArrayList保存下一行的childView                mAllViews.add(lineViews);                lineWidth=0;                lineViews =new ArrayList<>();            }            /**             * 如果不需要换行,则累加             */            lineWidth+=childWidth+lp.leftMargin+lp.rightMargin;            lineHeight=Math.max(lineHeight,childHeight+lp.topMargin+lp.bottomMargin);            lineViews.add(child);        }        // 记录最后一行        mLineHeight.add(lineHeight);        mAllViews.add(lineViews);        int left = 0;        int top = 0;        // 得到总行数        int lineNums = mAllViews.size();        for (int i=0;i<lineNums;i++){            // 每一行的所有的views            lineViews=mAllViews.get(i);            lineHeight=mLineHeight.get(i);            // 遍历当前行所有的View            for (int j=0;j<lineViews.size();j++){                View child = lineViews.get(j);                if (child.getVisibility() == View.GONE)                {                    continue;                }                MarginLayoutParams lp = (MarginLayoutParams) child                        .getLayoutParams();                //计算childView的left,top,right,bottom                int lc = left + lp.leftMargin;                int tc = top + lp.topMargin;                int rc =lc + child.getMeasuredWidth();                int bc = tc + child.getMeasuredHeight();                child.layout(lc, tc, rc, bc);                left += child.getMeasuredWidth() + lp.rightMargin                        + lp.leftMargin;            }            left = 0;            top += lineHeight;        }

自定义ViewGroup。
思路就是先测量父容器的大小和关键字的大小。再按宽度一个一个放进去。

2.引用
在主布局中引用这个类。

 <com.example.ly.myapplication.view.FlowLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:id="@+id/roottext"        android:layout_margin="5dp">    </com.example.ly.myapplication.view.FlowLayout>

这里需要动态生成textview,而不是一个一个写在xml文件里面。可以动态化控件

//list里放后台传过来的关键字数据 有多少数据可以创建多少roottext = (FlowLayout) find.findViewById(R.id.roottext);        for (int i=0;i<list.size();i++){            TextView tv=new TextView(this);            tv.setText(list.get(i));            tv.setBackgroundResource(R.drawable.flowlayout_text);            tv.setTextColor(getResources().getColor(R.color.black_font));            LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);            lp.setMargins(5,5,5,5);            tv.setLayoutParams(lp);            roottext.addView(tv);        }

在drawable里写textview的样式。(AS里drawable放自定义样式,mipmap放图片)

<shape xmlns:android="http://schemas.android.com/apk/res/android" >    <solid android:color="@color/white"/>    <stroke android:width="1dp"        android:color="@color/gray"        />    <corners android:radius="2dp"/>    <padding        android:bottom="2dp"        android:left="10dp"        android:right="10dp"        android:top="2dp" /></shape>

结果图:

结果图:

1 0
原创粉丝点击