android 自定义流布局。实现热门标签。开源库SimpleFlowLayout
前言
实际项目中需要实现一个 热门搜索 的栏目,类似下图:

由于 子项(子view) 中的文字是可变的,一行能显示的 子项 的个数也无法确定。需要支持自动换行和计算位置。
开源类库
我自己写了个 自定义view ,继承自viewGroup, 来实现它,托管到github开源平台。
地址:https://github.com/vir56k/SimpleFlowLayout
特点:可以不断添加多个子view,计算位置,自动换行。 类似html中的div标签
适用: 热门标签
实现思路
要实现 自定义的viewgroup,需要:
1. 继承自 ViewGroup
2. 实现 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
这个方法用于测量 自己(自定义view)本身需要的宽度和高度
3. 实现 protected void onLayout(boolean changed, int l, int t, int r, int b)
这个方法用于指定如何摆放 子view 的位置。
实现代码
package zhangyf.vir56k.flowframelayout; import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup; /**
* name: android 简单的流布局自定义view
* 作者:张云飞
* 特点:可以不断添加多个子view,计算位置,自动换行。
* 适用: 热门标签
* Created by zhangyunfei on 15/12/4.
*/
public class SimpleFlowLayout extends ViewGroup {
public SimpleFlowLayout(Context context) {
super(context);
} public SimpleFlowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
} public SimpleFlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMax = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMax = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthNeed = 0;
int heightNeed = 0;
int x = 0;
int y = 0;
int currentLineHeight = 0;
View child;
for (int i = 0; i < getChildCount(); i++) {
child = getChildAt(i);
if (child.getVisibility() == View.GONE) {
continue;
} child.measure(widthMeasureSpec, heightMeasureSpec);
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();//获得子view的 外边距
//测算子view宽度,本行这句代码有问题,不能计算子view的自动换行 int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
//使用viewGroup的measureChildWithMargins测算宽度,在这个方法里处理了 LayoutParams的match_parent等方式的处理
int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; if (x + childWidth > widthMax) {//换行处理,本行高度和x轴都清零,y轴下移(加上上次的行高)
y += currentLineHeight;
currentLineHeight = 0;
x = 0;
}
x += childWidth;
currentLineHeight = Math.max(currentLineHeight, childHeight); widthNeed = Math.max(widthNeed, x);//加入了这个 子view后,留下最大宽度
heightNeed = Math.max(heightNeed, y + currentLineHeight);//对比上次的,留下最大的高度
}
setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthMax : widthNeed,
heightMode == MeasureSpec.EXACTLY ? heightMax : heightNeed);
} @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int widthMax = getWidth();
int x, y;
x = 0;
y = 0;
View child;
int left = 0;
int top = 0;
int currentLineHeight = 0;
for (int i = 0; i < getChildCount(); i++) {
child = getChildAt(i);
if (child.getVisibility() == View.GONE) {
continue;
}
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
if (x + childWidth > widthMax) {//换行处理
y += currentLineHeight;
x = 0;
currentLineHeight = 0;
}
left = x + lp.leftMargin;
top = y + lp.topMargin;
//定位子view的位置
child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight()); x += childWidth;
currentLineHeight = Math.max(currentLineHeight, childHeight);
}
} @Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
} }
android 自定义流布局。实现热门标签。开源库SimpleFlowLayout的更多相关文章
- Android 自定义View修炼-Android中常见的热门标签的流式布局的实现
一.概述:在日常的app使用中,我们会在android 的app中看见 热门标签等自动换行的流式布局,今天,我们就来看看如何 自定义一个类似热门标签那样的流式布局吧(源码下载在下面最后给出哈) 类似的 ...
- Android(常用)主流UI开源库整理
这几天刚做完一个项目..有点空余时间,就想着吧这一两年做的项目中的UI界面用到的一些库整理一下.后来想了一下,既然要整理,就把网上常用的 AndroidUI界面的主流开源库 一起整理一下,方便查看. ...
- iOS 热门高效开源库集锦,收藏备用
一.推荐使用的第三方库 1:基于响应式编程思想的ReactiveCocoa 地址:https://github.com/ReactiveCocoa/ReactiveCocoa 2:iOS解耦与组件化开 ...
- Android控件进阶-自定义流式布局和热门标签控件
技术:Android+java 概述 在日常的app使用中,我们会在android 的app中看见 热门标签等自动换行的流式布局,今天,我们就来看看如何 自定义一个类似热门标签那样的流式布局吧,类 ...
- Android 开源库获取途径整理
介绍眼下收藏 Android 开源库比較多的 GitHub 项目.站点.Twitter.App 及怎样获取最新的 Android 开源库. 微信号: 1. GitHub Android 开源项目汇总 ...
- android开源库发布到jcenter图文详解与填坑
相信很多人都用过开源项目,特别是android studio普及以后,使用开源库更方便简单.而如何上传开源库到jcenter供大家方便使用,虽然网上也有教程,但还是遇坑了,最后总结一下,希望可以帮助大 ...
- Android 使用SwipeActionAdapter开源库实现简单列表的左右滑动操作
我们做listview左右滑动操作时,一般中情况下,都是像QQ那样,左滑弹出操作菜单(删除.编辑),然后选择菜单操作: 这样的效果不可谓不好,算是非常经典. 另外,有少数的APP,尤其是任务管理类的A ...
- 粉笔网iPhone端使用的第三方开源库
粉笔网iPhone端使用的第三方开源库 前言 最近有朋友问我粉笔网 iPhone 端使用了哪些第三方的开源库.我在这儿整理了一下,分享给大家. ASIHttpRequest ASIHttpReques ...
- Android主流UI开源库整理(转载)
http://www.jianshu.com/p/47a4a7b99364 标题隐含了两个层面的意思,一个是主流,另一个是UI.主流既通用,一些常规的按钮.Switch.进度条等控件都是通用控件,因此 ...
随机推荐
- python 字符串编码 ,区别 utf-8 和utf-8-sig
Python 读取文件首行多了"\ufeff"字符串 python读取B.txt文件时,控制台打印首行正常,但是若是用首行内容打开文本的话,就会报错: Traceback (mos ...
- wifiphisher 钓鱼工具的使用
wifiphisher 钓鱼工具的使用一.简介 Wifiphisher是一个安全工具,具有安装快速.自动化搭建的优点,利用它搭建起来的网络钓鱼攻击WiFi可以轻松获得密码和其他凭证.与其它(网络钓鱼) ...
- 发一些靠谱的招聘网站(含ios)
近日整理一些 招聘网站 , 欢迎大家 推荐 http://www.zhaopin.com 智联,貌似这货上市了.. http://www.51job.com 51job 还行 大街就不提了.0. ...
- 运行jar乱码问题
请使用 1.java -jar -Dfile.encoding=utf-8 dapao.jar 2.请使用URLDecode,URLEncode 3.请使用unicode编码格式 bat运行当前目录 ...
- JSP中四种传递参数中文乱码问题
查看来源:http://blog.csdn.net/hackerain/article/details/6776083
- 用Duplex实现消息广播
WCF中定义3种消息交换模式: 1. Request/Reply; 2. One-Way; 3. Duplex. Request/Reply 是缺省模式,即同步调用.在调用服务方法后需要等待服务的消 ...
- WCF推送
http://www.cnblogs.com/server126/archive/2011/08/11/2134942.html
- 深入理解Linux内核-访问文件
文件的访问模式:1.规范模式:2.同步模式:3.内存映射模式:4.直接I\O模式5.异步模式: 内存映射模式:1.共享型:在线性区页上的任何写操作都会修改磁盘上的文件:而且这种修改对映射了同一文件的所 ...
- R语言之——字符串处理函数
nchar 取字符数量的函数 length与nchar不同,length是取向量的长度 # nchar表示字符串中的字符的个数 nchar("abcd") [1] 4 # leng ...
- Dynamic Control Flow in ML
https://arxiv.org/abs/1805.01772 https://www.leiphone.com/news/201702/cb7cPOtzFj1pgRpk.html