欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义ViewGroup之FlowLayout(三)

程序员文章站 2024-03-07 08:58:26
本篇继续来讲自定义viewgroup,给大家带来一个实例:flowlayout。何为flowlayout,就是控件根据viewgroup的宽,自动的往右添加,如果当前行剩余...

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

Android自定义ViewGroup之FlowLayout(三)

定义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> 

 效果图如下:

Android自定义ViewGroup之FlowLayout(三)

源码下载:http://xiazai.jb51.net/201609/yuanma/android-flowlayout(jb51.net).rar

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