当前位置: 移动技术网 > 移动技术>移动开发>Android > Android自定义ViewGroup之FlowLayout(三)

Android自定义ViewGroup之FlowLayout(三)

2019年07月24日  | 移动技术网移动技术  | 我要评论

本篇继续来讲自定义viewgroup,给大家带来一个实例:flowlayout。何为flowlayout,就是控件根据viewgroup的宽,自动的往右添加,如果当前行剩余空间不足,则自动添加到下一行,所以也叫流式布局。android并没有提供流式布局,但是某些场合中,流式布局还是非常适合使用的,比如关键字标签,搜索热词列表等,比如下图:


定义flowlayout

layoutparams,onlayout的写法都和上一篇讲waterfalllayout一模一样,在此不再赘述了,没看过的可以参照上一篇android自定义viewgroup(二)之waterfalllayout
在这里主要说的是onmeasure方法,注释见下方:

 @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); 

 int childcount = getchildcount();
 // 如果是wrap_content情况下,记录宽和高 
 int wrapwidth = 0; 
 int wrapheight = 0; 
 //记录每一行的宽度,width不断取最大宽度 
 int linewidth = 0; 
 //每一行的高度,累加至height 
 int lineheight = 0;

 // 遍历每个子元素 
 for (int i = 0; i < childcount; i++) { 
 view child = getchildat(i); 
 // 测量每一个child的宽和高 
 measurechild(child, widthmeasurespec, heightmeasurespec); 
 // 得到child的lparams 
 layoutparams lparams = (layoutparams) child.getlayoutparams(); 
 // 当前子空间实际占据的宽度 
 int childwidth = child.getmeasuredwidth(); 
 // 当前子空间实际占据的高度 
 int childheight = child.getmeasuredheight(); 
 // 如果加上当前child,则超出最大宽度,然后开启新行 
 if (linewidth + childwidth > sizewidth) {
 //记录新行头一个标签坐标,为onlayout做准备
 lparams.left = 0;
 lparams.top = wrapheight + lineheight + vspace;
 lparams.right = childwidth;
 lparams.bottom = lparams.top + childheight;
 //取最大的,注意这里linewidth是包括右侧hspace的,需要减掉 
 wrapwidth = math.max(linewidth - hspace, childwidth); 
 // 重新开启新行,开始记录,可以看到行宽包括最右侧hspace 
 linewidth = childwidth + hspace;
 // 叠加当前高度,同理,加上下侧vspace
 wrapheight += lineheight + vspace;
 // 开启记录下一行的高度 
 lineheight = childheight; 
 } else {
 //记录每一个标签坐标,为onlayout做准备
 lparams.left = linewidth;
 lparams.top = wrapheight;
 lparams.right = lparams.left + childwidth;
 lparams.bottom = lparams.top + childheight;
 //在本行追加标签,累加值到linewidth,lineheight取最大高度 
 linewidth += childwidth + hspace;
 lineheight = math.max(lineheight, childheight);
 } 
 // 如果是最后一个
 if (i == childcount - 1) {
 //将当前记录的最大宽度和当前linewidth做比较,取较大值
 wrapwidth = math.max(wrapwidth, linewidth - hspace);
 //布局高加上最后一行高
 wrapheight += lineheight; 
 } 
 } 
 setmeasureddimension((modewidth == measurespec.exactly) ? sizewidth : wrapwidth, (modeheight == measurespec.exactly) ? sizeheight : wrapheight); 
 }

使用flowlayout

直接看xml吧,一看便知:

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 xmlns:attr="http://schemas.android.com/apk/res/com.hx.flowlayout"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="#e1e6f6"
 android:orientation="vertical" >

 <com.hx.flowlayout.flowlayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_margin="10dp"
 attr:hspace="20"
 attr:vspace="10">

 <textview
 style="@style/flow_text_style_1"
 android:text="标签" />

 <textview
 style="@style/flow_text_style_1"
 android:text="welcome" />

 <textview
 style="@style/flow_text_style_1"
 android:text="it工程师" />

 <textview
 style="@style/flow_text_style_1"
 android:text="程序猿" />

 <textview
 style="@style/flow_text_style_1"
 android:text="android" />

 <textview
 style="@style/flow_text_style_1"
 android:text="java" />

 <textview
 style="@style/flow_text_style_1"
 android:text="viewgroup" />

 <textview
 style="@style/flow_text_style_1"
 android:text="flowlayout" />
 </com.hx.flowlayout.flowlayout>

 <com.hx.flowlayout.flowlayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_margin="10dp"
 attr:hspace="20"
 attr:vspace="10">

 <textview
 style="@style/flow_text_style_2"
 android:text="标签" />

 <textview
 style="@style/flow_text_style_2"
 android:text="welcome" />

 <textview
 style="@style/flow_text_style_2"
 android:text="it工程师" />

 <textview
 style="@style/flow_text_style_2"
 android:text="程序猿" />

 <textview
 style="@style/flow_text_style_2"
 android:text="android" />

 <textview
 style="@style/flow_text_style_2"
 android:text="java" />

 <textview
 style="@style/flow_text_style_2"
 android:text="viewgroup" />

 <textview
 style="@style/flow_text_style_2"
 android:text="flowlayout" />
 </com.hx.flowlayout.flowlayout>
</linearlayout>

这里写的比较啰嗦,所有textview都是写在xml里面的,当然我们也可以通过java代码来动态添加。

再来看看style吧,这里我们定义了两种不同的风格,具体见下面:

 <style name="flow_text_style_1">
 <item name="android:layout_width">wrap_content</item>
 <item name="android:layout_height">wrap_content</item>
 <item name="android:background">@drawable/flow_text_bg_1</item>
 <item name="android:textcolor">#ffffff</item>
 <item name="android:textsize">16sp</item>
 </style>

 <style name="flow_text_style_2">
 <item name="android:layout_width">wrap_content</item>
 <item name="android:layout_height">wrap_content</item>
 <item name="android:background">@drawable/flow_text_bg_2</item>
 <item name="android:textcolor">#4b0082</item>
 <item name="android:textsize">20sp</item>
 </style>

找到background我们再进去看看,这里使用的是shapedrawable,之后我会写一些关于shapedrawable的文章:

<?xml version="1.0" encoding="utf-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android" > 
 <solid android:color="#ffffff"/> 
 <corners android:radius="40dp"/> 
 <stroke android:color="#c9c9c9" android:width="2dp"/> 
 <padding 
 android:bottom="2dp" 
 android:left="10dp" 
 android:right="10dp" 
 android:top="2dp" /> 
</shape> 

 效果图如下:

源码下载:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网