Android自定义ViewGroup之FlowLayout(三)
程序员文章站
2024-03-07 08:58:26
本篇继续来讲自定义viewgroup,给大家带来一个实例:flowlayout。何为flowlayout,就是控件根据viewgroup的宽,自动的往右添加,如果当前行剩余...
本篇继续来讲自定义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>
效果图如下:
源码下载:http://xiazai.jb51.net/201609/yuanma/android-flowlayout(jb51.net).rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
Android自定义View基础开发之图片加载进度条
-
Android动画效果之自定义ViewGroup添加布局动画(五)
-
Android笔记 自定义View(三):Canvas、Paint介绍
-
Android之自定义实现BaseAdapter(通用适配器二)
-
Android之自定义实现BaseAdapter(通用适配器一)
-
Android自定义View之圆形进度条式按钮
-
Android开发进阶自定义控件之滑动开关实现方法【附demo源码下载】
-
Android开发之自定义控件用法详解
-
Android自定义ViewGroup之WaterfallLayout(二)
-
Android开发之自定义CheckBox