一、概述:在日常的app使用中,我们会在android 的app中看见 热门标签等自动换行的流式布局,今天,我们就来看看如何

自定义一个类似热门标签那样的流式布局吧(源码下载在下面最后给出)

类似的自定义布局。下面我们就来详细介绍流式布局的应用特点以及用的的技术点:

1.流式布局的特点以及应用场景

特点:当上面一行的空间不够容纳新的TextView时候,

才开辟下一行的空间

原理图:

场景:主要用于关键词搜索或者热门标签等场景

2.自定义ViewGroup,重点重写下面两个方法

1、onMeasure:测量子view的宽高,设置自己的宽和高

2、onLayout:设置子view的位置

onMeasure:根据子view的布局文件中属性,来为子view设置测量模式和测量值

测量=测量模式+测量值;

测量模式有3种:

EXACTLY:表示设置了精确的值,一般当childView设置其宽、高为精确值、match_parent时,ViewGroup会将其设置为EXACTLY;

AT_MOST:表示子布局被限制在一个最大值内,一般当childView设置其宽、高为wrap_content时,ViewGroup会将其设置为AT_MOST;

UNSPECIFIED:表示子布局想要多大就多大,一般出现在AadapterView的item的heightMode中、ScrollView的childView的heightMode中;此种模式比较少见。

3.LayoutParams

ViewGroup LayoutParams :每个 ViewGroup 对应一个 LayoutParams; 即 ViewGroup -> LayoutParams

getLayoutParams 不知道转为哪个对应的LayoutParams ,其实很简单,就是如下:

子View.getLayoutParams 得到的LayoutParams对应的就是 子View所在的父控件的LayoutParams;

例如,LinearLayout 里面的子view.getLayoutParams ->LinearLayout.LayoutParams

所以 咱们的FlowLayout 也需要一个LayoutParams,由于上面的效果图是子View的 margin,

所以应该使用MarginLayoutParams。即FlowLayout->MarginLayoutParams

4.最后来看看实现的最终效果图:

二、热门标签的流式布局的实现:

1. 自定义热门标签的ViewGroup实现

根据上面的技术分析,自定义类继承于ViewGroup,并重写 onMeasure和onLayout等方法。具体实现代码如下:

package com.czm.flowlayout;

import java.util.ArrayList;

import java.util.List;

import android.content.Context;

import android.util.AttributeSet;

import android.view.View;

import android.view.ViewGroup;

/**

*

* @author caizhiming

* @created on 2015-4-13

*/

public class XCFlowLayout extends ViewGroup{

//存储所有子View

private List> mAllChildViews = new ArrayList<>();

//每一行的高度

private List mLineHeight = new ArrayList<>();

public XCFlowLayout(Context context) {

this(context, null);

// TODO Auto-generated constructor stub

}

public XCFlowLayout(Context context, AttributeSet attrs) {

this(context, attrs, 0);

// TODO Auto-generated constructor stub

}

public XCFlowLayout(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

// TODO Auto-generated constructor stub

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

// TODO Auto-generated method stub

//父控件传进来的宽度和高度以及对应的测量模式

int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);

int modeWidth = MeasureSpec.getMode(widthMeasureSpec);

int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);

int modeHeight = MeasureSpec.getMode(heightMeasureSpec);

//如果当前ViewGroup的宽高为wrap_content的情况

int width = 0;//自己测量的 宽度

int height = 0;//自己测量的高度

//记录每一行的宽度和高度

int lineWidth = 0;

int lineHeight = 0;

//获取子view的个数

int childCount = getChildCount();

for(int i = 0;i

View child = getChildAt(i);

//测量子View的宽和高

measureChild(child, widthMeasureSpec, heightMeasureSpec);

//得到LayoutParams

MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();

//子View占据的宽度

int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;

//子View占据的高度

int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;

//换行时候

if(lineWidth + childWidth > sizeWidth){

//对比得到最大的宽度

width = Math.max(width, lineWidth);

//重置lineWidth

lineWidth = childWidth;

//记录行高

height += lineHeight;

lineHeight = childHeight;

}else{//不换行情况

//叠加行宽

lineWidth += childWidth;

//得到最大行高

lineHeight = Math.max(lineHeight, childHeight);

}

//处理最后一个子View的情况

if(i == childCount -1){

width = Math.max(width, lineWidth);

height += lineHeight;

}

}

//wrap_content

setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width,

modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height);

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

}

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

// TODO Auto-generated method stub

mAllChildViews.clear();

mLineHeight.clear();

//获取当前ViewGroup的宽度

int width = getWidth();

int lineWidth = 0;

int lineHeight = 0;

//记录当前行的view

List lineViews = new ArrayList();

int childCount = getChildCount();

for(int i = 0;i

View child = getChildAt(i);

MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();

int childWidth = child.getMeasuredWidth();

int childHeight = child.getMeasuredHeight();

//如果需要换行

if(childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width){

//记录LineHeight

mLineHeight.add(lineHeight);

//记录当前行的Views

mAllChildViews.add(lineViews);

//重置行的宽高

lineWidth = 0;

lineHeight = childHeight + lp.topMargin + lp.bottomMargin;

//重置view的集合

lineViews = new ArrayList();

}

lineWidth += childWidth + lp.leftMargin + lp.rightMargin;

lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin);

lineViews.add(child);

}

//处理最后一行

mLineHeight.add(lineHeight);

mAllChildViews.add(lineViews);

//设置子View的位置

int left = 0;

int top = 0;

//获取行数

int lineCount = mAllChildViews.size();

for(int i = 0; i

//当前行的views和高度

lineViews = mAllChildViews.get(i);

lineHeight = mLineHeight.get(i);

for(int j = 0; j

View child = lineViews.get(j);

//判断是否显示

if(child.getVisibility() == View.GONE){

continue;

}

MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();

int cLeft = left + lp.leftMargin;

int cTop = top + lp.topMargin;

int cRight = cLeft + child.getMeasuredWidth();

int cBottom = cTop + child.getMeasuredHeight();

//进行子View进行布局

child.layout(cLeft, cTop, cRight, cBottom);

left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;

}

left = 0;

top += lineHeight;

}

}

/**

* 与当前ViewGroup对应的LayoutParams

*/

@Override

public LayoutParams generateLayoutParams(AttributeSet attrs) {

// TODO Auto-generated method stub

return new MarginLayoutParams(getContext(), attrs);

}

}

2.相关的布局文件:

引用自定义控件:

xmlns:tools="http://schemas.android.com/tools"

android:id="@+id/container"

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:id="@+id/flowlayout"

android:layout_width="match_parent"

android:layout_height="match_parent" >

TextView的样式文件:

android:left="5dp"

android:right="5dp"

android:top="5dp"

android:bottom="5dp"

/>

三、使用该自定义布局控件类

最后,如何使用该自定义的热门标签控件类呢?很简单,请看下面实例代码:

package com.czm.flowlayout;

import android.app.Activity;

import android.graphics.Color;

import android.os.Bundle;

import android.view.ViewGroup.LayoutParams;

import android.view.ViewGroup.MarginLayoutParams;

import android.widget.TextView;

/**

*

* @author caizhiming

* @created on 2015-4-13

*/

public class MainActivity extends Activity {

private String mNames[] = {

"welcome","android","TextView",

"apple","jamy","kobe bryant",

"jordan","layout","viewgroup",

"margin","padding","text",

"name","type","search","logcat"

};

private XCFlowLayout mFlowLayout;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initChildViews();

}

private void initChildViews() {

// TODO Auto-generated method stub

mFlowLayout = (XCFlowLayout) findViewById(R.id.flowlayout);

MarginLayoutParams lp = new MarginLayoutParams(

LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);

lp.leftMargin = 5;

lp.rightMargin = 5;

lp.topMargin = 5;

lp.bottomMargin = 5;

for(int i = 0; i

TextView view = new TextView(this);

view.setText(mNames[i]);

view.setTextColor(Color.WHITE);

view.setBackgroundDrawable(getResources().getDrawable(R.drawable.textview_bg));

mFlowLayout.addView(view,lp);

}

}

}

四、源码下载

此源码下载完之后,往往有个要点我们容易忽略,那就是源码的安全性问题,此处可点击移动应用安全智能服务提供商爱加密的Android加密,源码保护!

android 流失标签,Android中常见的热门标签的流式布局的实现相关推荐

  1. android搜索热词(热门标签)流式布局的实现

    先看下效果图 1.流式布局实现 继承ViewGroup,重写onMeasure,onLayout方法.代码如下: package com.example.lin.flowlayoutdemo;impo ...

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

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

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

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

  4. android 流失布局,GitHub - hongyangAndroid/FlowLayout: [不再维护]Android流式布局,支持单选、多选等,适合用于产品标签等。...

    FlowLayout Android流式布局,支持单选.多选等,适合用于产品标签等. ##特色 以setAdapter形式注入数据 直接设置selector为background即可完成标签选则的切换 ...

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

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

  6. android 流失布局,Android使用RecyclerView实现流式布局的注意事项

    纯手打,不喜勿喷 long may the sun shine 众所周知,Android开发中Recycleview的功能十分强大,可以实现各种炫酷的效果,今天我根据最近开发的一个项目简要说下流式布局 ...

  7. HTML中常见的其它标签

    HTML中常见的其它标签 一.头标签部分 1.<title>:指定浏览器的标题栏显示的内容. 2.<base>: href 属性:指定网页中所有的超链接的目录.可以是本地目录, ...

  8. 深度学习中常见的打标签工具和数据集资源

    深度学习中常见的打标签工具和数据集资源 一.打标签工具 1. labelimg/labelme 1.1 搭建图片标注环境(win10) (1) 安装anaconda3 (2) 在anaconda环境p ...

  9. android 历史搜索布局,《Android APP可能有的东西》之UI篇:流式标签搜索历史

    说在前面 很多APP都有热门排行热门搜索什么的,这个时候可能需要用到标签,也就是流式布局,而还有可能用到的就是搜索历史记录,这种一般都是使用listview展示.但是,相当有可能是反过来的UI展示效果 ...

最新文章

  1. Leetcode 之Binary Tree Postorder Traversal(44)
  2. muxer、demuxer muxer是什么?视频封装、解封装(逆封装)
  3. Python技术基础知识点:OS模块的应用
  4. 查看oracle连接客户端
  5. MATLAB对图片格式批量转换
  6. websocket(二)--简单实现网页版群聊
  7. 米斯特白帽培训讲义 挖掘篇
  8. 家长又放心了一些!教育类App不能再干这些事了
  9. 泛函编程(29)-泛函实用结构:Trampoline-不再怕StackOverflow
  10. MariaDB和MySQL性能测试比较
  11. 如何在heroku上部署你的Django程序
  12. ​越狱iOS必备神器Flex使用指南-屏蔽越狱检测的破解利器
  13. 谈谈EOS的出块时间,不可逆时间,BFT
  14. 年底了,你总结了吗?我先来。
  15. JAVA做SEO优化,CMS最有效的SEO优化8大方法
  16. TestCenter Layer4-7分析
  17. 滤波电容值得选取-ESR
  18. 【java校招你不知道的那些事儿】java校招有没有考点大纲?不能拿面试补缺
  19. DNF服务器该如何选择?
  20. Cesium:结合canvas添加渐变背景色

热门文章

  1. python自动化测试视频教程_精品系列-悠悠python自动化测试视频教程
  2. 一朋友手头有98万,想在深圳买房,网友的回复很扎心!
  3. 输变电设备物联网传感器数据通信规约_物联网大潮来袭,无线通讯模块如何连接未来?...
  4. NXP ZigBee JN5169开发环境搭建
  5. java assembly 打包_使用Maven的assembly插件实现自定义打包
  6. 常用输入设备——键盘、鼠标、手写输入与触摸屏、传感器
  7. java getproperty_System.getProperty()方法大全
  8. 从0自学成AI高手,她只用了一个产假
  9. Hadoop集群搭建教程(超级版本2.0)
  10. AI时代,智能客服如何赋能客服行业?