package com.loaderman.customviewdemo;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup; public class FlowLayout extends ViewGroup {
public FlowLayout(Context context) {
super(context);
} public FlowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
} public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
} /**
* 父容器生成 子view 的布局LayoutParams;
* 一句话道出LayoutParams的本质:LayoutParams是Layout提供给其中的Children使用的。
* 如果要自定义ViewGroup支持子控件的layout_margin参数,则自定义的ViewGroup类必须重载generateLayoutParams()函数,
* 并且在该函数中返回一个ViewGroup.MarginLayoutParams派生类对象,这样才能使用margin参数。
*/
@Override
protected LayoutParams generateLayoutParams(
LayoutParams p)
{
return new MarginLayoutParams(p);
} @Override
public LayoutParams generateLayoutParams(AttributeSet attrs)
{
return new MarginLayoutParams(getContext(), attrs);
} @Override
protected LayoutParams generateDefaultLayoutParams()
{
return new MarginLayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int measureWidth = MeasureSpec.getSize(widthMeasureSpec);
int measureHeight = MeasureSpec.getSize(heightMeasureSpec);
int measureWidthMode = MeasureSpec.getMode(widthMeasureSpec);
int measureHeightMode = MeasureSpec.getMode(heightMeasureSpec); int lineWidth = 0;
int lineHeight = 0;
int height = 0;
int width = 0;
int count = getChildCount();
for (int i=0;i<count;i++){
View child = getChildAt(i);
measureChild(child,widthMeasureSpec,heightMeasureSpec);
//如果忘记重写generateLayoutParams,则hild.getLayoutParams()将不是MarginLayoutParams的实例
//在强制转换时就会出错,此时我们把左右间距设置为0,但由于在计算布局宽高时没有加上间距值,就是计算出的宽高要比实际小,所以是onLayout时就会出错
MarginLayoutParams lp = null;
if (child.getLayoutParams() instanceof MarginLayoutParams) {
lp = (MarginLayoutParams) child
.getLayoutParams();
}else{
lp = new MarginLayoutParams(0,0);
}
int childWidth = child.getMeasuredWidth() + lp.leftMargin +lp.rightMargin;
int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; if (lineWidth + childWidth > measureWidth){
//需要换行
width = Math.max(lineWidth,width);
height += lineHeight;
//因为由于盛不下当前控件,而将此控件调到下一行,所以将此控件的高度和宽度初始化给lineHeight、lineWidth
lineHeight = childHeight;
lineWidth = childWidth;
}else{
// 否则累加值lineWidth,lineHeight取最大高度
lineHeight = Math.max(lineHeight,childHeight);
lineWidth += childWidth;
} //最后一行是不会超出width范围的,所以要单独处理
if (i == count -1){
height += lineHeight;
width = Math.max(width,lineWidth);
} }
//当属性是MeasureSpec.EXACTLY时,那么它的高度就是确定的,
// 只有当是wrap_content时,根据内部控件的大小来确定它的大小时,大小是不确定的,属性是AT_MOST,此时,就需要我们自己计算它的应当的大小,并设置进去
setMeasuredDimension((measureWidthMode == MeasureSpec.EXACTLY) ? measureWidth
: width, (measureHeightMode == MeasureSpec.EXACTLY) ? measureHeight
: height);
} @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int count = getChildCount();
int lineWidth = 0;
int lineHeight = 0;
int top=0,left=0;
for (int i=0; i<count;i++){
View child = getChildAt(i);
MarginLayoutParams lp = (MarginLayoutParams) child
.getLayoutParams();
int childWidth = child.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;
int childHeight = child.getMeasuredHeight()+lp.topMargin+lp.bottomMargin; if (childWidth + lineWidth >getMeasuredWidth()){
//如果换行,当前控件将跑到下一行,从最左边开始,所以left就是0,而top则需要加上上一行的行高,才是这个控件的top点;
top += lineHeight;
left = 0;
//同样,重新初始化lineHeight和lineWidth
lineHeight = childHeight;
lineWidth = childWidth;
}else{
lineHeight = Math.max(lineHeight,childHeight);
lineWidth += childWidth;
}
//计算childView的left,top,right,bottom
int lc = left + lp.leftMargin;
int tc = top + lp.topMargin;
int rc =lc + child.getMeasuredWidth();
int bc = tc + child.getMeasuredHeight();
child.layout(lc, tc, rc, bc);//布局控件
//将left置为下一子控件的起始点
left+=childWidth;
} } }
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ff00ff"
tools:context=".MainActivity"> <com.loaderman.customviewdemo.FlowLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
style="@style/text_flag_01"
android:background="@drawable/flag_03"
android:text="Welcome"
android:textColor="@android:color/white" /> <TextView
style="@style/text_flag_01"
android:background="@drawable/flag_03"
android:text="IT工程师"
android:textColor="@android:color/white" /> <TextView
style="@style/text_flag_01"
android:background="@drawable/flag_03"
android:text="我真是可以的"
android:textColor="@android:color/white" /> <TextView
style="@style/text_flag_01"
android:background="@drawable/flag_03"
android:text="你觉得呢"
android:textColor="@android:color/white" /> <TextView
style="@style/text_flag_01"
android:background="@drawable/flag_03"
android:text="不要只知道挣钱"
android:textColor="@android:color/white" /> <TextView
style="@style/text_flag_01"
android:background="@drawable/flag_03"
android:text="努力ing"
android:textColor="@android:color/white" /> <TextView
style="@style/text_flag_01"
android:background="@drawable/flag_03"
android:text="I thick i can"
android:textColor="@android:color/white" />
</com.loaderman.customviewdemo.FlowLayout>
</LinearLayout>

效果:

FlowLayout实现的更多相关文章

  1. 【Java布局】FlowLayout布局时设定组件大小

    默认的JPanel中,采用的是FlowLayout布局 下面是api中的定义: JPanel(boolean isDoubleBuffered)           创建具有 FlowLayout 和 ...

  2. Android自定义实现FlowLayout

    实现FlowLayout 何为FlowLayout,如果对Java的Swing比较熟悉的话一定不会陌生,就是控件根据ViewGroup的宽,自动的往右添加,如果当前行剩余空间不足,则自动添加到下一行. ...

  3. 转:Java图形化界面设计——布局管理器之FlowLayout(流式布局)其他请参考转载出处网址

    http://blog.csdn.net/liujun13579/article/details/7771191 前文讲解了JFrame.JPanel,其中已经涉及到了空布局的使用.Java虽然可以以 ...

  4. Java SE (1)之 JFrame 组件 FlowLayout 布局

    package com.sunzhiyan; import java.awt.*; import java.awt.event.*; import javax.swing.*; public clas ...

  5. iOS流布局UICollectionView使用FlowLayout进行更灵活布局

    一.引言 前面的博客介绍了UICollectionView的相关方法和其协议中的方法,但对布局的管理类UICollectionViewFlowLayout没有着重探讨,这篇博客介绍关于布局的相关设置和 ...

  6. Java图形化界面设计——布局管理器之FlowLayout(流式布局)

    一.布局管理器所属类包 所属类包 布局管理器名称 说明 Java.awt FlowLayout(流式布局) 组件按照加入的先后顺序按照设置的对齐方式从左向右排列,一行排满到下一行开始继续排列 Bord ...

  7. 5、Java Swing布局管理器(FlowLayout、BorderLayout、CardLayout、BoxLayout、GirdBagLayout 和 GirdLayout)

    5.Java-Swing常用布局管理器       应用布局管理器都属于相对布局,各组件位置可随界面大小而相应改变,不变的只是其相对位置,布局管理器比较难以控制,一般只在界面大小需要改是才用,但即使这 ...

  8. Swing-布局管理器之FlowLayout(流式布局)-入门

    FlowLayout应该是Swing布局管理器学习中最简单.最基础的一个.所谓流式,就是内部控件像水流一样,从前到后按顺序水平排列,直到达到容器的宽度时跳转到第二行.既然是水平排列,那么就存在三种基本 ...

  9. FlowLayout OnSizeChanged

    在FlowLayout里加了20个控件,当窗口变化时,改变这20个控件的宽高,结果发现在直接点最大化时, 计算不正确导致自身的滚动条出不来.把改变大小的代码直接添加Form窗口的onSizeChagn ...

  10. Android -- 自定义ViewGroup实现FlowLayout效果

    1,在开发的时候,常在我们的需求中会有这种效果,添加一个商品的一些热门标签,效果图如下: 2,从上面效果可以看得出来,这是一个自定义的ViewGroup,然后实现换行效果,让我们一起来实现一下 自定义 ...

随机推荐

  1. 更改Ubuntu下默认Python版本

    更改Ubuntu下默认Python版本 首先查看系统内有哪些版本的Python ls /usr/bin/python* 查看当前python版本 python --version 基于用户修改默认版本 ...

  2. SpringBoot下,@WebFilter配置获取日志

    CREATE TABLE [dbo].[SWEBSERVICELOG]( [WLG_ID] [varchar](100) NOT NULL, [WLG_SESSIONID] [varchar](100 ...

  3. 别人家的java语言编写的自动化测试系统

    https://gitee.com/testdevops/easyrest 但是我还不会用 ~~~~(>_<)~~~~ 目前的状况是:大概知道流程了,可是第一个用例就跑步起来 自己想写一些 ...

  4. MySQL进阶12-- 数据类型介绍: 数值型/字符型/日期型-- 正负溢出保护/枚举型/set型/时间戳

    /*进阶12 SQL 数据类型介绍 数值型: 整数: Tinyint(1b) < mediumint(3b)<smallint(2b) <int(4b) <bigint(8b) ...

  5. 【PAT-并查集-水题】L2-007-家庭房产

    L2-007. 家庭房产 给定每个人的家庭成员和其自己名下的房产,请你统计出每个家庭的人口数.人均房产面积及房产套数. 输入格式: 输入第一行给出一个正整数N(<=1000),随后N行,每行按下 ...

  6. Vue实现一个图片懒加载插件(转载)

    Vue是可以自定义指令的,最近学习过程中遇见了一个需要图片懒加载的功能,最后参考了别人的代码和思路自己重新写了一遍.以下将详细介绍如何实现自定义指令v-lazyload. 先看如何使用这个指令: &l ...

  7. Sql Server2008——远程过程调用失败

    今天正在敲机房,清理软件提醒垃圾太多并且电脑也特别卡,我就想着既然这样就清理一下得了,结果就是:No zuo No die,SQL server数据库连接不上了.不过从另一方面来说这也是一次学习的机会 ...

  8. Mysql 安装,及其闪退的问题解决

    1.下载 Mysql 64下载链接(华军软件) http://soft.onlinedown.net/soft/3573.htm 2.安装 2.1 傻瓜式安装 不再赘述,略过. 2.2安装完成打开闪退 ...

  9. Spring Cloud Eureka 注册中心高可用机制

    一.Eureka 正常工作流程 Service 服务作为 Eureka Client 客户端需要在启动的时候就要向 Eureka Server 注册中心进行注册,并获取最新的服务列表数据. Eurek ...

  10. HaspMap和ConcurrentHashMap

    参考自:http://www.importnew.com/28263.html HaspMap和ConcurrentHashMap(康科瑞特哈希迈普) Java7 HashMap 不支持并发操作,Ha ...