前言

实际项目中需要实现一个 热门搜索 的栏目,类似下图:

由于 子项(子view) 中的文字是可变的,一行能显示的 子项 的个数也无法确定。需要支持自动换行和计算位置。

开源类库

我自己写了个 自定义view ,继承自viewGroup, 来实现它,托管到github开源平台。

名称:SimpleFlowLayout

地址: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的更多相关文章

  1. Android 自定义View修炼-Android中常见的热门标签的流式布局的实现

    一.概述:在日常的app使用中,我们会在android 的app中看见 热门标签等自动换行的流式布局,今天,我们就来看看如何 自定义一个类似热门标签那样的流式布局吧(源码下载在下面最后给出哈) 类似的 ...

  2. Android(常用)主流UI开源库整理

    这几天刚做完一个项目..有点空余时间,就想着吧这一两年做的项目中的UI界面用到的一些库整理一下.后来想了一下,既然要整理,就把网上常用的 AndroidUI界面的主流开源库 一起整理一下,方便查看. ...

  3. iOS 热门高效开源库集锦,收藏备用

    一.推荐使用的第三方库 1:基于响应式编程思想的ReactiveCocoa 地址:https://github.com/ReactiveCocoa/ReactiveCocoa 2:iOS解耦与组件化开 ...

  4. Android控件进阶-自定义流式布局和热门标签控件

    技术:Android+java   概述 在日常的app使用中,我们会在android 的app中看见 热门标签等自动换行的流式布局,今天,我们就来看看如何 自定义一个类似热门标签那样的流式布局吧,类 ...

  5. Android 开源库获取途径整理

    介绍眼下收藏 Android 开源库比較多的 GitHub 项目.站点.Twitter.App 及怎样获取最新的 Android 开源库. 微信号: 1. GitHub Android 开源项目汇总 ...

  6. android开源库发布到jcenter图文详解与填坑

    相信很多人都用过开源项目,特别是android studio普及以后,使用开源库更方便简单.而如何上传开源库到jcenter供大家方便使用,虽然网上也有教程,但还是遇坑了,最后总结一下,希望可以帮助大 ...

  7. Android 使用SwipeActionAdapter开源库实现简单列表的左右滑动操作

    我们做listview左右滑动操作时,一般中情况下,都是像QQ那样,左滑弹出操作菜单(删除.编辑),然后选择菜单操作: 这样的效果不可谓不好,算是非常经典. 另外,有少数的APP,尤其是任务管理类的A ...

  8. 粉笔网iPhone端使用的第三方开源库

    粉笔网iPhone端使用的第三方开源库 前言 最近有朋友问我粉笔网 iPhone 端使用了哪些第三方的开源库.我在这儿整理了一下,分享给大家. ASIHttpRequest ASIHttpReques ...

  9. Android主流UI开源库整理(转载)

    http://www.jianshu.com/p/47a4a7b99364 标题隐含了两个层面的意思,一个是主流,另一个是UI.主流既通用,一些常规的按钮.Switch.进度条等控件都是通用控件,因此 ...

随机推荐

  1. Appium 设置手机连接方式

    使用appium的 Connection 和driver 的setConnection方法,可以切换手机的上网方式 // 切换到wifi Connection cnn = Connection.WIF ...

  2. 基础003_V7-Memory Resources

    一.综述 参考ug473.pdf. 常用Memory 资源: 在IP核中,Block memory(distributed memory为CLB中的资源): 通常选用Native,而不用AXI接口: ...

  3. 微信小程序JS导出和导入

    1. 导出 1.1 方法和变量导出(写在被导出方法和变量的js文件) module.exports = { variable: value, method : methodName } 1.2 cla ...

  4. CentOS SVN强制用户提交时写日志

    问题:在项目提交时候不写日志,在后期查看修改历史时需要对比版本才知道提交原因.解决方案:在svn服务端通过hooks在提交时强制要求写日志.#!/bin/shREPOS="$1"T ...

  5. Android Studio 通过 git update 或者 pull 的时候出错及解决办法

    Android Studio 通过 git update 或者 pull 的时候出错,log 如下: Couldn't save uncommitted changes. Tried to save ...

  6. MQ有啥用

    Q:最近看了一些MSMQ的资料,感觉很是奇怪,在IIS中装上此服务后,感觉这东西就像一个小数据库一样,暂时保存一些发送过来的数据,然后另一端再去收取?A:是的. Q:这样有什么用呢?直接在数据库中建立 ...

  7. MYSQL拒绝访问:not allowed to connect解决方法

    分享下MYSQL拒绝访问报错not allowed to connect的解决方法. 可以在其它任何的主机上以root身份登录 mysql报如下错误,截取部分, message from server ...

  8. ASP.NET CORE中控制器内return HTML 内容自动编码问题

    以前ASP.NET MVC中在控制器中直接 return Content( "<h1>测试测试</h1>"); 在前台VIEW上就显示加粗的文字了,但是在A ...

  9. BNUOJ 34982 Beautiful Garden

    BNUOJ 34982 Beautiful Garden 题目地址:BNUOJ 34982 题意:  看错题意纠结了好久... 在坐标轴上有一些树,如今要又一次排列这些树,使得相邻的树之间间距相等.  ...

  10. lua--clone

    clone 深度克隆一个值. 格式: value = clone(值) 用法示例: -- 下面的代码,t2 是 t1 的引用,修改 t2 的属性时,t1 的内容也会发生变化 , b = } local ...