流式布局,好处就是父类布局可以自动的判断子孩子是不是需要换行,什么时候需要换行,可以做到网页版的标签的效果。今天就是简单的做了自定义的流式布局。

具体效果:


原理:
其实很简单,Measure  Layout。只需要这两个步骤就可以搞定了。完全的手动去Measure  Layout。
我们看一下代码。
解释就在代码里面做注释了,因为使用为知笔记写的博客,格式不符合代码格式。大家可以看具体的源码。最后又源码下载地址。
1.Measure  测量 
 
         @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        
        int lineHeight = 0 ;
        int lineWidth = 0 ; 
        
        int width = 0 ; 
        int height = 0 ; 
        
        int childCount = getChildCount();
        
        Log.i("Test", getPaddingLeft() + "==right="  +getPaddingRight());
        
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            measureChild(childView, widthMeasureSpec, heightMeasureSpec);
            MarginLayoutParams params = (MarginLayoutParams)                                       childView.getLayoutParams();
            
            int childWidth = childView.getMeasuredWidth() + params.leftMargin + params.rightMargin ; 
            
            int childHeight  = childView.getMeasuredHeight() + params.topMargin + params.bottomMargin ; 
            
            
            if ((lineWidth + childWidth ) > widthSize - getPaddingLeft() - getPaddingRight() ) {
                width = Math.max(width, lineWidth);
                lineWidth = childWidth ; 
                height += lineHeight ; 
                lineHeight = childHeight; 
            }else {
                lineWidth += childWidth ; 
                lineHeight = Math.max(lineHeight, childHeight);
            }
            
            
            if (i  == childCount-1) {
                width = Math.max(width, lineWidth);
                height += lineHeight ; 
            }
        }
        
        height += getPaddingTop() + getPaddingBottom() ;
        
        setMeasuredDimension(widthMode == MeasureSpec.EXACTLY?widthSize:width, 
                heightMode == MeasureSpec.EXACTLY?heightSize:height);

}



2.onLayout  布局
 @Override
    protected void onLayout(boolean a, int l, int t, int r, int b) {
        
        childViewList.clear(); 
        
        int childCount = getChildCount() ; 
        int width = getWidth();
        int lineWidth = 0 ;
        int lineHeight = 0 ; 
        
        List<View> lineViews = new ArrayList<View>();
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            MarginLayoutParams params = (MarginLayoutParams) childView.getLayoutParams();
            
            int childWidth = childView.getMeasuredWidth() + params.leftMargin + params.rightMargin ; 
            int childHeight = childView.getMeasuredHeight() + params.topMargin +  params.bottomMargin  ;
            
            if (lineWidth + childWidth > width - getPaddingLeft() - getPaddingRight()) {
                
                childViewList.add(lineViews);
                lineViews = new ArrayList<View>();
                
                if (i == 0 ) {
                    lineHeight += getPaddingTop() ; 
                }else if (i== childCount - 1) {
                    lineHeight += getPaddingBottom() ; 
                }
                this.lineHeight.add(lineHeight);
                
                lineHeight = 0 ; 
                lineWidth = 0 ; 
            }
            
            lineWidth += childWidth; 
            lineHeight = Math.max(lineHeight, childHeight) ;
            
            lineViews.add(childView);
        }
        
        childViewList.add(lineViews);
        this.lineHeight.add(lineHeight);
        
        int left = getPaddingLeft() ;
        int top = getPaddingTop(); 
        
        for (int i = 0; i < childViewList.size(); i++) {
            lineViews = childViewList.get(i);
            for (int j = 0; j < lineViews.size(); j++) {
                View childView = lineViews.get(j);
                
                MarginLayoutParams params = (MarginLayoutParams) childView.getLayoutParams();
                
                int lc = left + params.leftMargin ; 
                int tc = top + params.topMargin ; 
                int rc = lc + childView.getMeasuredWidth()  ; 
                int bc = tc + childView.getMeasuredHeight() ; 
                
                childView.layout(lc,tc,rc,bc);
                
                left += params.leftMargin + childView.getMeasuredWidth() + params.rightMargin ; 
            }
            
            left =  getPaddingLeft() ;
            top += this.lineHeight.get(i) ; 
        }

}


代码下载地址:
 百度网盘:  http://pan.baidu.com/s/1hqH1kFU 


附件列表

Android自定义之流式布局的更多相关文章

  1. 自定义ViewGroup 流式布局

    使用 public class MainActivity extends Activity {     @Override     protected void onCreate(Bundle sav ...

  2. 28 自定义View流式布局

    流式布局每行的行高以本行中最高的元素作为高,如果一个元素放不下到一行时直接到第二行 FlowLayoutView package com.qf.sxy.customview05.widget; imp ...

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

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

  4. 自定义View(三)--实现一个简单地流式布局

    Android中的流式布局也就是常说的瀑布流很是常见,不仅在很多项目中都能见到,而且面试中也有很多面试官问道,那么什么是流式布局呢?简单来说就是如果当前行的剩余宽度不足以摆放下一个控件的时候,则自动将 ...

  5. Android 自动换行流式布局的RadioGroup

    效果图 用法 使用FlowRadioGroup代替RadioGroup 代码 import android.content.Context; import android.util.Attribute ...

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

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

  7. 【Android - 自定义View】之自定义可滚动的流式布局

    首先来介绍一下这个自定义View: (1)这个自定义View的名称叫做 FlowLayout ,继承自ViewGroup类: (2)在这个自定义View中,用户可以放入所有继承自View类的视图,这个 ...

  8. 自定义流式布局:ViewGroup的测量与布局

    目录 1.View生命周期以及View层级 1.1.View生命周期 1.2.View层级 2.View测量与MeasureSpec类 2.1.MeasureSpec类 2.2.父View的限制 :测 ...

  9. Android流式布局实现

    查看我的所有开源项目[开源实验室] 欢迎增加我的QQ群:[201055521],本博客client下载[请点击] 摘要 新项目用到了一种全新布局----Android标签流式布局的功能,正好一直说给大 ...

随机推荐

  1. 动态数组 - vector

    #include <iostream> #include <vector> // 头文件 using namespace std; int main() { vector< ...

  2. mysql id_logfile 日志

    ib_logfile 文件原理 ib_logfile0 是innodb中事务日志,记录系统的回滚,重做日志,记录的是文件的物理更改,存放位置my.ini 中的 datadir="D:\php ...

  3. php 实现无限极分类

    原始数据 $array = array( array('id' => 1, 'pid' => 0, 'n' => '河北省'), array('id' => 2, 'pid' ...

  4. Training set,Gallery set 和Probe set的区别

    这段时间看了CVPR2017的这篇论文”SphereFace:Deep Hypersphere Embedding for Face Recognition" 里面有提到Probe set, ...

  5. 有关eval用法的小结

    首先要明白eval.这个是可以把字符串代码,直接当做js运行.比如 var ss="alert(1);";这个时候ss保存的是文本. 使用 eval(ss);这样就相当于,执行了s ...

  6. PIE SDK专题制图保存模板

    1.    功能简介 在PIE SDK中,所有的制图元素.视图范围以及排版等都可以保存成一个模板,以供多次重复使用.使用模板时只需要打开该模板,加载相应数据,就可以直接出图,省去了重复制作图幅的麻烦, ...

  7. Mac下Jenkins+SVN+Xcode构建持续导出环境

    1 安装Jenkins Jenkins是基于Java开发的一种持续集成工具.所以呢,要使用Jenkins必须使用先安装JDK. JDK安装 JDK 下载地址 jdk 1.8.png 安装JDK的过程略 ...

  8. Java基础17-成员变量、return关键字和多参方法

    1.成员变量 在类中声明的变量为成员变量 //Dog类 class Dog{ String name;//成员变量 } public class Test1{ public static void m ...

  9. SQL Server 2008 SQL2012 SQL2014 收缩日志 清空删除大日志文件

    SQL2008 SQL2012 SQL2014 的收缩日志 由于SQL2008对文件和日志管理进行了优化,所以以下语句在SQL2005中可以运行但在SQL2008中已经被取消:(SQL2005)Bac ...

  10. 成功配置TOMCAT的LOG4J日志系统,格式:HTML+每天以YYYY-MM-DD.LOG命名的日志文件

    关于log4j.properties文件在web项目中放的位置,找过很多,最后实践结果是: 一.web项目 二.放在src的目录里面,然后项目生成后会自动在\WEB-INF\classes文件里有份l ...