先看下效果图

1、流式布局实现

继承ViewGroup,重写onMeasure,onLayout方法。代码如下:

package com.example.lin.flowlayoutdemo;import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;import java.util.ArrayList;
import java.util.List;/*** Created by lin.zhou on 2015/8/12.* 流式布局*/
public class YhFlowLayout extends ViewGroup {private List<Line> mLines = new ArrayList<Line>(); // 用来记录描述有多少行Viewprivate Line mCurrrenLine;                                            // 用来记录当前已经添加到了哪一行private int mHorizontalSpace = 10;private int mVerticalSpace = 6;public YhFlowLayout(Context context, AttributeSet attrs) {super(context, attrs);}public YhFlowLayout(Context context) {super(context);}public void setSpace(int horizontalSpace, int verticalSpace) {this.mHorizontalSpace = horizontalSpace;this.mVerticalSpace = verticalSpace;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//清空mLines.clear();mCurrrenLine = null;int layoutWidth = MeasureSpec.getSize(widthMeasureSpec);// 获取行最大的宽度int maxLineWidth = layoutWidth - getPaddingLeft() - getPaddingRight();//测量孩子int count = getChildCount();for (int i = 0; i < count; i++) {View v = getChildAt(i);//如果孩子不可见if (v.getVisibility() == GONE) {continue;}measureChild(v, widthMeasureSpec, heightMeasureSpec);// 往lines添加孩子if (mCurrrenLine == null) {// 说明还没有开始添加孩子mCurrrenLine = new Line(maxLineWidth, mHorizontalSpace);// 添加到 Lines中mLines.add(mCurrrenLine);// 行中一个孩子都没有mCurrrenLine.addView(v);} else {// 行中有孩子了Boolean canAdd = mCurrrenLine.canAdd(v);if (canAdd) {mCurrrenLine.addView(v);} else {//装不下,换行mCurrrenLine = new Line(maxLineWidth, mHorizontalSpace);mLines.add(mCurrrenLine);// 将view添加到linemCurrrenLine.addView(v);}}}// 设置自己的宽度和高度int measuredWidth = layoutWidth;float allHeight = 0;for (int i = 0; i < mLines.size(); i++) {float mHeigth = mLines.get(i).mHeigth;// 加行高allHeight += mHeigth;// 加间距if (i != 0) {allHeight += mVerticalSpace;}}int measuredHeight = (int) (allHeight + getPaddingTop() + getPaddingBottom() + 0.5f);setMeasuredDimension(measuredWidth, measuredHeight);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {// 给Child 布局---> 给Line布局int paddingLeft = getPaddingLeft();int offsetTop = getPaddingTop();for (int i = 0; i < mLines.size(); i++) {Line line = mLines.get(i);// 给行布局line.layout(paddingLeft, offsetTop);offsetTop += line.mHeigth + mVerticalSpace;}}class Line {// 属性private List<View> mViews = new ArrayList<View>();    // 用来记录每一行有几个Viewprivate float mMaxWidth;                            // 行最大的宽度private float mUsedWidth;                        // 已经使用了多少宽度private float mHeigth;                            // 行的高度private float mMarginLeft;private float mMarginRight;private float mMarginTop;private float mMarginBottom;private float mHorizontalSpace;                    // View和view之间的水平间距// 构造public Line(int maxWidth, int horizontalSpace) {this.mMaxWidth = maxWidth;this.mHorizontalSpace = horizontalSpace;}// 方法/*** 添加view,记录属性的变化** @param view*/public void addView(View view) {// 加载View的方法int size = mViews.size();int viewWidth = view.getMeasuredWidth();int viewHeight = view.getMeasuredHeight();// 计算宽和高if (size == 0) {// 说还没有添加Viewif (viewWidth > mMaxWidth) {mUsedWidth = mMaxWidth;} else {mUsedWidth = viewWidth;}mHeigth = viewHeight;} else {// 多个view的情况mUsedWidth += viewWidth + mHorizontalSpace;mHeigth = mHeigth < viewHeight ? viewHeight : mHeigth;}// 将View记录到集合中mViews.add(view);}/*** 用来判断是否可以将View添加到line中** @param view* @return*/public boolean canAdd(View view) {// 判断是否能添加Viewint size = mViews.size();if (size == 0) {return true;}int viewWidth = view.getMeasuredWidth();// 预计使用的宽度float planWidth = mUsedWidth + mHorizontalSpace + viewWidth;if (planWidth > mMaxWidth) {// 加不进去return false;}return true;}/*** 给孩子布局** @param offsetLeft* @param offsetTop*/public void layout(int offsetLeft, int offsetTop) {// 给孩子布局int currentLeft = offsetLeft;int size = mViews.size();// 判断已经使用的宽度是否小于最大的宽度float extra = 0;float widthAvg = 0;if (mMaxWidth > mUsedWidth) {extra = mMaxWidth - mUsedWidth;widthAvg = extra / size;}for (int i = 0; i < size; i++) {View view = mViews.get(i);int viewWidth = view.getMeasuredWidth();int viewHeight = view.getMeasuredHeight();// 判断是否有富余if (widthAvg != 0) {// 改变宽度int newWidth = (int) (viewWidth + widthAvg + 0.5f);int widthMeasureSpec = MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY);int heightMeasureSpec = MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.EXACTLY);view.measure(widthMeasureSpec, heightMeasureSpec);viewWidth = view.getMeasuredWidth();viewHeight = view.getMeasuredHeight();}// 布局int left = currentLeft;int top = (int) (offsetTop + (mHeigth - viewHeight) / 2 +0.5f);// int top = offsetTop;int right = left + viewWidth;int bottom = top + viewHeight;view.layout(left, top, right, bottom);currentLeft += viewWidth + mHorizontalSpace;}}}
}

2、Demo演示

布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="wrap_content"android:layout_height="wrap_content"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"><com.example.lin.flowlayoutdemo.YhFlowLayout
        android:id="@+id/flowlayout"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"></com.example.lin.flowlayoutdemo.YhFlowLayout>
</RelativeLayout>

下面根据需求设置一些流失布局中标签的属性:

 private void displayUI() {for (int i = 0; i < mDatas.size(); i++) {final String data = mDatas.get(i);TextView tv = new TextView(this);tv.setText(data);tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);tv.setGravity(Gravity.CENTER);int paddingy = DisplayUtils.dp2Px(this, 7);int paddingx = DisplayUtils.dp2Px(this, 6);tv.setPadding(paddingx, paddingy, paddingx, paddingy);tv.setClickable(false);int shape = GradientDrawable.RECTANGLE;int radius = DisplayUtils.dp2Px(this, 4);int strokeWeight = DisplayUtils.dp2Px(this, 1);int stokeColor = getResources().getColor(R.color.text_color_gray);int stokeColor2 = getResources().getColor(R.color.green);GradientDrawable normalBg = DrawableUtils.getShape(shape, radius, strokeWeight, stokeColor, Color.WHITE);GradientDrawable pressedBg = DrawableUtils.getShape(shape, radius, strokeWeight, stokeColor2, getResources().getColor(R.color.green));StateListDrawable selector = DrawableUtils.getSelector(normalBg, pressedBg);tv.setBackgroundDrawable(selector);ColorStateList colorStateList = DrawableUtils.getColorSelector(getResources().getColor(R.color.text_color_gray), getResources().getColor(R.color.white));tv.setTextColor(colorStateList);tv.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {}});flowLayout.addView(tv);}}

如果需要设置viewgroup的间距

   flowLayout = (YhFlowLayout)findViewById(R.id.flowlayout);flowLayout.setSpace(DisplayUtils.dp2Px(this, 5), DisplayUtils.dp2Px(this, 5));flowLayout.setPadding(DisplayUtils.dp2Px(this, 5), DisplayUtils.dp2Px(this, 5),DisplayUtils.dp2Px(this, 5), DisplayUtils.dp2Px(this, 5));

ok,现在好看多了。

3、下面贴demo的下载地址

http://download.csdn.net/detail/zhoulin541/9574989

android搜索热词(热门标签)流式布局的实现相关推荐

  1. 自定义 FlowLayout流式布局搜索框 加 GreenDao存取搜索记录,使用RecyclerView展示

    输入框布局的shape <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android ...

  2. 流式布局FlowLayout支持行数控制,单选,多选,点击等操作

    最近有这么一个需求,如下图 开发中内容搜索页面经常会记录搜索关键字,搜索关键字长度不一,我们通过会采用自定义流布局的方式展示:流布局的基本需要是动态添加childView并实现自动换行操作,这个操作比 ...

  3. android 流失标签,Android中常见的热门标签的流式布局的实现

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

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

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

  5. android实现标签功能,Android实现热门标签的流式布局

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

  6. Android第三方流式布局FlowLayout简单实用(搜索历史记录)

    效果图: 导入大Model下: maven { url 'https://jitpack.io' } builde.gradle依赖: implementation 'com.github.LRH19 ...

  7. android 搜索历史流布局,FlowLayout流式布局实现搜索清空历史记录

    本文实例为大家分享了FlowLayout实现搜索清空历史记录的具体代码,供大家参考,具体内容如下 效果图:点击搜索框将搜索的历史在流式布局中展示出来,清空历史记录就会将历史清空,每次搜索后都存入sp中 ...

  8. android 自定义flowlayout,Android 流式布局FlowLayout 实现关键字标签

    FlowLayout Android 流式布局FlowLayout 实现关键字标签 效果图 使用方法 在项目根目录的build.gradle文件中加入如下代码 maven { url "ht ...

  9. Android自定义流式布局-FlowLayout

    很多App在搜索页时都有对热门标签的一个排列,而Android官方没有对应的布局控件,所以自己写了一个流式布局(也称标签布局)--FlowLayout. 为了大家使用的方便,没有添加自定义属性,所以需 ...

最新文章

  1. 网络与服务器编程框架库 acl_3.0.13 发布
  2. C#程序输出信息到调试窗口的几种方式
  3. 1.2.4 在Python中使用向量化的技巧和注意事项
  4. 线性回归损失函数为什么要用平方形式
  5. 我的世界 文件保存位置
  6. 继承thread类创建线程
  7. php常用linux命令httpd,Linux常用的100个命令
  8. ZJOI2008 树的统计 树链剖分学习
  9. 去除在页面上点击出现的大片蓝色
  10. 代码投毒、删库跑路,开源生态链安全该如何保证?
  11. 跟我学Kafka之zookeeper的存储结构
  12. 华为BIOS系统升级
  13. 传感器实验——蜂鸣器
  14. 18650锂电池保护板接线图_锂电池保护板的基础知识及常见不良分析
  15. kettle Call From LAPTOP-14BPR3NI/192.168.1.2 to locahost:8020 failed on connection
  16. repo init 下载代码error.GitError: manifests ls-remote: usage: git ls-remote
  17. MYSQL学习整理(4):函数
  18. mysql---创建学生表
  19. VMware 日记一:基础的系统安装和基本配置解析
  20. 明治维新VS洋务运动-同途殊归的变革by高铭君儿

热门文章

  1. 29、 打家劫舍(一)(二)
  2. 承担刑事责任,是否影响子女前程
  3. python学习——进阶操作:根据数据绘制省份热力地图
  4. 轻舟已过万重山——真正的技术派公司是怎么联调、测试和发布的?
  5. 对于编程,实践和理论哪个更重要【最近有些事,没时间写文,就发篇水文吧,回头补】
  6. c语言程序设计胡成松,C语言程序设计教学课件 作者 胡成松 黄玉兰 李文红 课后习题解答 习题答案 4选择结构程序设计 .docx...
  7. Catia V5汽车设计实战教程
  8. excel日历弄到html,Excel中进行添加日历控件的两种方法
  9. 永恒之蓝漏洞简单分析
  10. 网站漏洞扫描软件wrbscanner_用于渗透测试的10种漏洞扫描工具